Find the answer to your Linux question:
Results 1 to 9 of 9
this runs:- using namespace std; #include <iostream> int main(){ int a=600123456; char buf[a]; return 0;} this does not run; it aborts with a Segmentation fault error:- using namespace std; #include ...
  1. #1
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16

    Segmentation Fault puzzle

    this runs:-
    using namespace std;
    #include <iostream>
    int main(){
    int a=600123456;
    char buf[a];

    return 0;}

    this does not run; it aborts with a Segmentation fault error:-
    using namespace std;
    #include <iostream>
    int main(){
    int a=9000000;
    char buf[a];
    cout<<a;
    return 0;}

    this runs:-
    using namespace std;
    #include <iostream>
    int main(){
    int a=8000000;
    char buf[a];
    cout<<a;
    return 0;}

    Why ? TOP reports 1.2GB unused RAM at the time!
    Do you get the same responses on your machine?
    Can you post an explanation please?

  2. #2
    Linux Engineer GNU-Fan's Avatar
    Join Date
    Mar 2008
    Posts
    935
    Hi,

    first of all, please use code tags when you post code. It is easier to read for anybody who comes by to help.

    While you "feed" the << operator of cout with an array of chars, you are responsible that the string ends with a `0` byte. Otherwise cout might try read beyond the array's boundaries, resulting in a seg fault.

    I am not sure if this is the real cause in this particular case, as it is very improbable that no 0 is found in 9000000 bytes. But it is not impossible.

    To be sure, try
    Code:
    char buf[a] = {0};
    Debian GNU/Linux -- You know you want it.

  3. #3
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16
    Thanks for replying.
    Sorry, i will try to remember to do so in future.
    All cout does is to print the value of a, which is either 9 or 8 million.
    buf never gets used; that's why i am so puzzled.
    The program exists only to illustrate the problem [which arrose in some other stuff i am trying to do]..

  4. #4
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    It would be interesting to know which line is segfaulting. If it's the array allocation, then I may have an idea, but it confuses me that the first program works in that case. Please change your code to the following, and tell us what the output is:
    Code:
    using namespace std;
    #include <iostream>
    int main()
    {
        int a=9000000;
        char buf[a];
        cerr << "Allocated buf" << endl;
        cout << a << endl;
        return 0;
    }
    If "Allocated buf" gets printed, then the error, for whatever reason, is on the printing of a.
    DISTRO=Arch
    Registered Linux User #388732

  5. #5
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Try making the array global...
    Make mine Arch Linux

  6. #6
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    This is a C program. You can't specify an automatic variable such as buf[a] using another variable. This is a compile time operation. You can use 'a' to specify the size of buf[] if it is a #define macro. If you really need to dynamically size buf[] based upon a variable or function argument, then what you need to do is this:
    Code:
    int a = 9000000;
    char* buf = (char*)malloc(a);
    .
    .
    .
    free(buf);
    or this:
    Code:
    int a = 9000000;
    char* buf = (char*)alloca(a);
    The second has the advantage of not needing to free the buffer to avoid a memory leak, but you are in danger of running out of stack space unless your system is configured properly.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  7. #7
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16
    Rubberman- do you mean this:
    Code:
    using namespace std;
    #include <iostream>
    int main(){
    int a=9000000;
    char* buf = (char*)alloca(a);
    cout<<a;
    return 0;}
    because it does not work on mine. In GDB it gives:

    Program received signal SIGSEGV, Segmentation fault.
    0x08048778 in main () at segmentation.cpp:6
    6 cout<<a;
    (gdb)

    Cabhan- it segfaulted on your line cerr<<....... .
    Gerard4143- it made no difference.

  8. #8
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    The memory returned by malloc/alloca has not been cleared - it contains bogus data. You are segfaulting here because you are trying to read a string that may not be terminated with a NUL byte, resulting in trying to read beyond the current stack. The calloc() function does zero out the memory returned. So, you need to do this:
    Code:
    using namespace std;
    #include <iostream>
    int main(){
        int a=9000000;
        char* buf = (char*)alloca(a);
        if (buf)
        {
            buf[0] = 0;
            cout<<a;
        }
        return 0;
    }
    As shown, you need to verify that the buffer did get allocated. Remember what I said about running out of stack? I think that most Linux systems are configured by default to allow about 8-10MB of stack per process, so allocating 9MB may not work unless you change your ulimit before you run the process. My allowed process stack space is currently set to 10240KB (10M). This is generally adequate unless you are using a lot of stack for temporary variables like you are, or you have massively recursive functions.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  9. #9
    Just Joined!
    Join Date
    Mar 2010
    Posts
    16
    Thanks.

    You are segfaulting here because you are trying to read a string that may not be terminated with a NUL byte
    But I'm only reading a, which is an integer not a string. The code does nothing to buf after its creation.

    After a lot of thrashing around reading up about your suggestions I've got the following to work:
    with calloc:
    Code:
    using namespace std;
    #include <iostream>
    int main(){
    int a=100123456; // about as much as it can manage;
    size_t b=a, c=4;
    int* buf = (int*)calloc(b,c);
    if (buf==0) { cout<<"noway"<<endl;}
    for (int i=0; i<a; i++) {buf[i]=i; if (i%1000000==0){cout<<"\n---"<<i;}}
    // fills buf and prints brief progress
    return 0;
    }
    and with malloc - gets killed @ i ~506 million:
    Code:
    using namespace std;
    #include <iostream>
    int main(){
    int a=700123456;
    size_t b=a, c=4;
    int* buf = (int*)malloc(b);
    if (buf==0) { cout<<"noway"<<endl;}
    for (int i=0; i<a; i++) {buf[i]=i; if (i%1000000==0){cout<<"\n---"<<i;}}
    // fills buf and prints brief progress
    return 0;}
    and another way - gets killed @ i ~126 million:

    Code:
    using namespace std;
    #include <iostream>
    
    int main(){
    int a=300123456;
    int * buf;
    buf=new (nothrow) int [a];
    if (buf==0) { cout<<"noway"<<endl;}
    for (int i=0; i<a; i++) {buf[i]=i; if (i%1000000==0){cout<<i<<"\n";}}
    // fills buf and prints brief progress
    return 0;
    }
    Is your machine permanently set to provide your C++ programs with 10MB? If so, how did you set it, because I'd really like to get past the unknown point-of-being-killed, which depends on time after machine boot up and previous code runs.

    However, your last code-post still SegFaults.

    This is a C program. You can't specify an automatic variable such as buf[a] using another variable.
    Generally true - I accept; nonetheless, the code works for arrays less than 8MB, why doesn't the compiler complain though?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...