1
/* 
INCLUDES & DEFINES
*/
#define _CRT_SECURE_NO_WARNINGS 1

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

#define N 10

#define LINE_LENGTH (65537*6) /* assuming we deal with integers. 65536 is the largest integer. each number in line offers a ' ' or '\0' and each number consists of 5 chars max.*/
#define STR_MAIN_ERROR_MSG "error occured while attempting to read data from file. aborted!\n"
#define STR_MENU "(a) print double-dynamic array.\n(b) add new number.\n(c) add new column.\n(d) remove last number.\n(e) remove last column.\n(q) quit program.\n\nEnter your choice: "
#define STR_MENU_INPUT_ERROR "Wrong Choice, try again.\n"
#define STR_MENU_QUIT "End of program, Thank you & good bye...\n"
#define STR_MENU_SHORT "Menu: ...\nEnter your choice: "
/*
FUNCTION DECLARATIONS
*/
int allocate_subarray(int**, const int);
int parse_line_data(char*,int**,const int);
int read_file_successful(int**);
void start_menu(int**);
void terminate(int**);

void funcA(const int**);
void funcB(int**);
void funcC(int**);
void funcD(int**);
void funcE(int**);
/*
MAIN FUNCTION BODY
*/
int main(){
    int *Array[N]={NULL};
    if ( read_file_successful(Array)) start_menu(Array);
    else printf("%s",STR_MAIN_ERROR_MSG);
    return 0;
}
/*
OTHER FUNCTION BODIES
*/
int allocate_subarray(int** p, const int size){
    *p=(int*)malloc(sizeof(int)*size);
    return (p!=NULL);
}
int parse_line_data(char *S, int **A, const int i){
    int j;
    int size=atoi(strtok(S," "));
    if(!allocate_subarray(&A[i], size)) return 0;
    for(j=0; j<size; j++) A[i][j]=atoi(strtok(NULL," "));
    return 1;
}
int read_file_successful(int** A){   /* <----- STACK OVERFLOW HAPPENS HERE. */
    FILE *f=fopen("input3.txt", "r");
    if(f){
        char line[LINE_LENGTH*N];
        int i;
        for(i=0; fgets(line,sizeof(line),f) && i<N; i++) 
            if (!(parse_line_data(line, A, i))) return 0;
        fclose(f);
        return 1;
    }
    return 0;
}
void start_menu(int **A){
    char choice;
    printf("%s",STR_MENU);
    do{
        scanf("%c",&choice);
        while(getchar()!='\n');
        switch(choice){
            case 'q': terminate(A); printf("%s",STR_MENU_QUIT); return;
            case 'a': funcA(A); break;
            case 'b': funcB(A); break;
            case 'c': funcC(A); break;
            case 'd': funcD(A); break;
            case 'e': funcE(A); break;
            default: printf("%s",STR_MENU_INPUT_ERROR);
        }
    } while(printf("%s",STR_MENU_SHORT));
}
void terminate(int **A){
    int i;
    for(i=0; i<N && A[i]; i++) free(A[i]);
}
/**/
void funcA(const int **A){}
void funcB(int **A){}
void funcC(int **A){}
void funcD(int **A){}
void funcE(int **A){}

Doing this favour for a friend, a basic program that reads lines from a text file, and converts them into integers stored in malloc allocated arrays (sizes given in text too). problem is, long time no C. debugging this beauty, and it gives me a stack overflow error message in the spot I commented for you. Tried different variations for the function parameter: int* A[] , int* A[N].. still trips me up @run-time.

Jason Evans
  • 28,906
  • 14
  • 90
  • 154
Igal Klebanov
  • 348
  • 2
  • 15
  • 2
    have you cropped anything out? Or is that everything? – weston Nov 27 '12 at 00:09
  • yeah i did, stuff that's irrelevant. – Igal Klebanov Nov 27 '12 at 00:10
  • 3
    This code works on [ideone](http://ideone.com/ivKC07) – janisz Nov 27 '12 at 00:10
  • 2
    @IgalKlebanov Does this example actually fail for you? It compiles and runs just fine for me. Are you sure what you stripped out isn't relevant? – Brian Campbell Nov 27 '12 at 00:12
  • 1
    What compiler are you using? Can you post complete code for read_file_successful function? – Nemanja Boric Nov 27 '12 at 00:13
  • 2
    Post more, or try this code yourself, cause I cant see anyway it would stack overflow – weston Nov 27 '12 at 00:13
  • edited the code.. using visual studio 2008. – Igal Klebanov Nov 27 '12 at 00:20
  • Note that you should write `#include ` etc. That's what the standard says; that's what you should do. – Jonathan Leffler Nov 27 '12 at 00:22
  • 1
    You're not making copies of the strings copied to the A array; that's going to cause problems eventually. I'm not convinced it produces the crash per se, but you'll need to review that part of the code. – Jonathan Leffler Nov 27 '12 at 00:28
  • @JonathanLeffler i use #include <> whenever im writing in C++. thing is, this program is an answer to a task given to students. i believe they teach #include "" in C courses. – Igal Klebanov Nov 27 '12 at 00:34
  • 1
    If they teach `#include "stdio.h"` in C courses, then give up on the course _now_; they are wrong to teach that. Most of the time, it won't actually matter, but it is not sensible to go against the examples in the standard which all use angle brackets. – Jonathan Leffler Nov 27 '12 at 00:36
  • @JonathanLeffler not supposed to keep the data from the text file. just convert to int anything in it, and pass the numbers into A[i][j]'s. the crash happens before this part of the code, and i don't get any compile-time errors or warnings. – Igal Klebanov Nov 27 '12 at 00:39
  • 1
    [WhozCraig](http://stackoverflow.com/users/1322972/whozcraig) has given you the answer; you're allocating more space on the stack than the system can manage. There've been several questions with this recently; it's funny, I don't remember them cropping up in previous years. – Jonathan Leffler Nov 27 '12 at 00:44
  • possible duplicate of [Max Array Size in C](http://stackoverflow.com/questions/13504807/max-array-size-in-c) – Jonathan Leffler Nov 27 '12 at 00:51
  • 2
    @JonathanLeffler not stack space, but the [111 gB global space](http://stackoverflow.com/questions/13461289/sorting-words-with-using-counting-sort#comment18412148_13461289) is still at the time of my all-time wtf-were-they-thinking list =P – WhozCraig Nov 27 '12 at 00:58

1 Answers1

3

You're allocating N * LINE_LENGTH stack space in read_file_successful(). Do the math. Thats 10 * 65537 * 6, or 3932220 bytes. thus blowing your stack.

char line[LINE_LENGTH*N];

where LINE_LENGTH is 65537*6 and N is 10.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • 1
    See also: [Max array size in C](http://stackoverflow.com/questions/13504807/max-array-size-in-c) (and [Why can't I define a two-dimensional array larger than 300x300](http://stackoverflow.com/questions/13518605/why-cant-i-define-a-two-dimensional-array-larger-than-300300), but that's closed as a duplicate of the other). – Jonathan Leffler Nov 27 '12 at 00:50
  • ok, so why on earth does it crash before this line? at "int read_file_successful(int** A){" – Igal Klebanov Nov 27 '12 at 00:51
  • 1
    @IgalKlebanov: Because it fails as it enters `main()` and tries to allocate space. Exactly where the problem will be spotted is undefined. It has to be before `read_file_successful()` gets going. – Jonathan Leffler Nov 27 '12 at 00:53
  • 1
    I can't quote the standard like Jonathan can, but I believe it is up to the implementation of the C compiler when stack space in functions is set aside. For C++ it is implementation-perogative for POD types, scope-mandated for non-POD types (so I've been led to believe, but others more familiar with the standard would be better equipped to state for sure). But for C, I'm pretty sure it is *entirely* at the behest of the implementation when the space is snagged, as far out as the function scope (which it did in your case). A quick asm-list of that function will expose for sure what I suspect. – WhozCraig Nov 27 '12 at 00:55
  • is malloc gonna work? or is LINE_LENGTH*N just way too much (even for the heap)?? – Igal Klebanov Nov 27 '12 at 01:01
  • 1
    @IgalKlebanov It would be fine for the heap, but do you *really* need almost 4MB of temporary line-buffer space to read *one* line at a time? From what your algorithm seems to do, I'm shocked you need that much space (remember, this is for a **per-line** read). Is your *input file* even that large, assuming it was all on one line?? I'm kinda doubting it. Sometimes "more" isn't better, it's just... more. – WhozCraig Nov 27 '12 at 01:05
  • char* line=(char*)malloc(sizeof(char)*LINE_LENGTH); will do. THANKS. – Igal Klebanov Nov 27 '12 at 01:22