Thread: use of printf prevents segfault!

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Unhappy use of printf prevents segfault!

    I'm writing a function that takes a file, reads the file into a buffer while keeping count of the lines, then takes each line and plugs the content into a simple structure. I did it that way because the number of lines is variable and will determine, obviously, the number of structs needed. So I get the number of lines (nofl) and in the middle of the function do this:

    struct thestruct new[nofl];

    I was getting a segfault, so to make sure nofl was correct, i inserted the following line RIGHT BEFORE the last one:

    printf("--%d--\n", nofl);

    AND NOW NO SEGFAULT!!! Nothing else is changed, but adding and subtracting that one line makes all the difference. Really, really, really. More observations:
    1) Up until now I've been declaring variables (inc. structs) at the beginning of a function, but I've never heard tell that it must be so. Does this have anything to do with it?
    2) The segfault actually occurs later when new[1] (ie. the 2nd struct in the array) is called on (it turns out not to exist).
    3) "nofl" is determined on the line immediately preceeding the printf statement.
    4) if I put the printf statement after the struct declaration, the segfault returns.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    You could post the code to make things more clear (if that's possible).
    1) You can declare variables in the middle like you do with new[] only with the C99 standard (i think)
    2) So a seg fault occurs after all, so the printf doesn't actually solve the problem, eh?
    3) As long as it is before it is ok
    4) I ll admit I had similar occasions that printf changed the seg fault. But in any case it doesn't solve the problem. Post the code to find exactly the problem.

  3. #3
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Sounds like a classic stack corruption. Can you post your code?

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by QuantumPete View Post
    Sounds like a classic stack corruption. Can you post your code?

    QuantumPete
    Or quite possibly writing over the end of your allocated data at some point previously.

    When problems change due to "irrelevant" changes in the code, it's usually because you are going across the line of some memory - adding/changing the code around will move the actual bits of memory used by different pieces of code, so the problem "moves", but it's actually not fixed, it's just overwriting something less harmful.

    For example, calling printf will make sure the variable is stored on the stack, whilst not calling printf will not use the stack to store the local variable - so some bytes less used on the stack, so when you overwrite the end of an array, it no longer overwrites the variable, but some important data [such as the frame pointer or return address of the function].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by matsp View Post
    Or quite possibly writing over the end of your allocated data at some point previously.
    My money is still on stack corruption

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by QuantumPete View Post
    My money is still on stack corruption

    QuantumPete
    Not at all saying you are wrong. Only reason I said overwriting dynamically allocated memory is that it's happening in new - but that's no good indication really.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by matsp View Post
    it's happening in new
    It looks to me like the variable is called new (how that got by the compiler I don't know), no dynamic allocation.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MK27
    In the meantime I heartily recommend people try ray[] for themselves...

    nofl so far is less than 100.
    hmm... I suggest that you post a minimal example of what is actually in the [...].

    I see two possibilities: you are accessing your array out of bounds but escaping unscathed by luck, or the C99 variable length array language feature is at work. If it is the latter, fine, but if it is the former, then you may pay a heavy price for your mistake in the future.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by laserlight View Post
    hmm... I suggest that you post a minimal example of what is actually in the [...].

    I see two possibilities: you are accessing your array out of bounds but escaping unscathed by luck, or the C99 variable length array language feature is at work. If it is the latter, fine, but if it is the former, then you may pay a heavy price for your mistake in the future.
    Since it is a global variable, I expect that it won't be "variable length array". And the warning the compiler gives is explcitly saying that it's giving a size of 1 - so there is only one element in the array called ray.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Cool

    I'm not sure what matsp's example is suppose to demonstrate -- that "accessing ray[]" will corrupt the other array? Why? Because the compiler handles arrays in the same way and hence the best chance of an overwrite is with another array?

    You & laserlight could be right about this, I'll let you know when my tish fits the hand. I'm not sure if ray[] will count in C99 "variable length array":
    http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
    But at least there's the possibility...boldly going and all that...

    [...] includes the determination of nofl (to recap: I'm doing what must be a common task -- reading a text file of indeterminate length, each line of which (eg. "name number section") is translated into a struct. I guess I could set ray[10000] or something.

    But as of yet, there's no problem...and this is in a gtk_main() context, so there's a lot of storage going on...

    I may have to investigate this "pragma" thing.

    nofl IS NOT global, and if you think about reading lines not, perhaps, even necessary. The warning about size of one is probably because ray[] appears to have no size at all. But in the for (i) loop, ray[i] does function and retain it's value globally.

    ps. my point about the warnings intrinsic to compiling, eg. the linux kernel and C libraries, would be that even the people who built all this can't seem to get rid of them. The one with strcasestr is:

    warning: assignment makes pointer from integer without a cast

    which doesn't appear with strstr (tho their use is identical).
    Last edited by MK27; 08-27-2008 at 09:22 AM. Reason: ps.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    But if anyone has an example of how to grow the array using malloc and realloc "properly" please post it (how do you cast an array of structs -- (struct **)realloc(?bytes?!!) -- i haven't tried...).
    Don't cast the result of malloc/calloc/realloc in C! It's in the FAQ!

    This reference isn't perfect, but it looks pretty good.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Regarding what you example is supposed to show: I choose an array because that the simplest way to create a few variables worth of memory that I could write some "pattern" to. Did you actually try to implement that?

    Your code probably will crash when you reach the next 4K boundary of ray - since we don't know what ray contains, it's impossible to predict when that would happen (and it may well be that other data is stored AFTER ray, and that it just happens that overwriting that causes nothing bad that you can detect). This is the problem with undefined behaviour - it's like crossing the road when "don't walk"/"red man" showing - some days you'd get across the road fine, other days you'd get run over by a bus, and further other days, Police Constable Plod grabs you by the collar and tells you off [yeah, ok, that's unlikely - but still...].

    As to strcasestr(), are you sure you added the red part in your source code?
    Code:
    #define _GNU_SOURCE
    #include <string.h>
    --
    Mats
    Last edited by matsp; 08-27-2008 at 09:36 AM. Reason: Fix tags.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    nofl IS NOT global, and if you think about reading lines not, perhaps, even necessary. The warning about size of one is probably because ray[] appears to have no size at all. But in the for (i) loop, ray[i] does function and retain it's value globally.
    Based on the available information (I still cannot fully understand variable length arrays as specified by C99 just by reading C99), I think matsp is right. ray is a global, so variable length arrays do not come into play here (from what I understand, the length of a variable length array is fixed for the duration of its lifetime: the length is variable in the sense that it is not fixed at compile time). Therefore it is just an array of length 1, in which case you have a case of array out of bounds access, which is a Bad Thing.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Okay! I tried it and matsp WAS WRONG!

    Code:
    #include <stdio.h>
    
    struct thest {
            int one;
            int two;
    } ray[];
    int array[10];
    
    int main () {   
            int i;
            for (i=0; i<10; i++) {
                    array[i] = i*3;
            }   
            for (i=0; i<=4; i++) {
                    ray[i].one = i;
                    ray[i].two = i*2;
            }   
            for (i=0; i<=4; i++) printf("ray[&#37;d]: %d\t%d\n", i,ray[i].one,ray[i].two);
            for (i=0; i<10; i++) {
                    if (array[i] != i*3) printf("array[%d] isn't %d, it's %d...\n",i,i*3,array[i]);
                    else puts("No problem");
            }
    }
    Sorry the "code" tags don't work here (?!?). But the output is:

    Code:
    ray[0]: 0       0
    ray[1]: 1       2
    ray[2]: 2       4
    ray[3]: 3       6
    ray[4]: 4       8
    No problem
    No problem
    No problem
    No problem
    No problem
    No problem
    No problem
    No problem
    No problem
    No problem
    But I clearly haven't hit a 4k boundary yet. Also,
    #define _GNU_SOURCE
    didn't make any difference with strcasestr.

    Of course, now all subsequent unexplained segfaults will leave me paranoid...
    Last edited by laserlight; 08-27-2008 at 10:20 AM. Reason: Fixed code tags: end with [/code], not [\code]
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #15
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by MK27 View Post
    Okay! I tried it and matsp WAS WRONG!
    Erm, actually, no he's not. It's up to the compiler how to arrange your variables in memory and it could well have put array before ray. Maybe because it arranges them by descending size or because of alignment. Pick a different compiler and you may well get a different result.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. IF CONDITION plese help
    By birumut in forum C Programming
    Replies: 12
    Last Post: 03-06-2009, 09:48 PM
  2. making it portable.....?
    By ShadeS_07 in forum C Programming
    Replies: 11
    Last Post: 12-24-2008, 09:38 AM
  3. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  4. Simple C question: user input to repeat a loop
    By evernaut in forum C Programming
    Replies: 2
    Last Post: 11-18-2006, 09:23 AM
  5. Drawing tables in C
    By stanoman in forum C Programming
    Replies: 5
    Last Post: 10-09-2003, 10:14 AM

Tags for this Thread