0

Edit: as requested I've included the code in 'ledic'. However, it never ran - any of it, not even a hello world printf as first line, so I am relatively sure the problem would never be withinit.

Edit2: ironically enough, it was within the 'ledic' function. Looks like I understand even less about this than I previously thought.

I am writing for my current project at Uni and no one around me can figure out this segmentation fault. It should be pretty straightforward so I appreciate your help.

Code as follows:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void ledic(FILE *fp){

    printf("Hello world\n");

    int len;
    int j, i, k;
    char palavra[30];
    char dictionary[30][10000][30];
    int VecOcorrencias[30];


    for (j=0; j<30; j++)
    VecOcorrencias[j]=0;

    printf("Hello world\n");

    while ( fscanf(fp, "%s", palavra) == 1 ) {

        len = strlen(palavra);
        k = VecOcorrencias[len];
        strcpy (dictionary[len][k], palavra);
        VecOcorrencias[len]++;
    }
for (i=0; i<1000; i++)
printf("%s %d\n", dictionary[5][i], VecOcorrencias[5]);
}

}

FILE *OpenFile( char *nome, char *mode){

FILE *fp;
fp = fopen (nome, mode);
if( fp == NULL){
    printf(" Cant open file\n");
    exit(1);
}

return (fp);
}

int main( int argc, char *argv[]){

FILE * fp;

fp = OpenFile( argv[1], "r");

ledic(fp);

return(0);

}

The code breaks when it enters the void ledic(FILE *fp) function, and says it cannot access the referenced memory (I suppose *fp).

I cannot for the life of me figure out why. Any thoughts?

aqueiro
  • 43
  • 4
  • 1
    What is the code inside your `ledic` function? Please include this in your question. – byxor Nov 18 '16 at 17:41
  • 2
    It's probably something you do in `ledic()` that's problematic. Can you post `ledic()`'s code? Preferably a [MCVE]. – P.P Nov 18 '16 at 17:42
  • The problem ist most likely in the `ledic` function which you didn't show... On my computer the code you posted works just fine. – Jabberwocky Nov 18 '16 at 17:45
  • I've included the code in 'ledic'. However, as stated at the end of my post, the code breaks at the very declaration of the function. It never runs past that point, as in, it doesn't print the Hello World. Can you explain why that code is relevant? – aqueiro Nov 18 '16 at 17:51
  • 2
    Please try this: `char dictionary[30][10000][30];` -> `static char dictionary[30][10000][30];` and tell us if the problem goes away. A precise answer will follow depending on what you tell us. – Jabberwocky Nov 18 '16 at 17:53
  • Well, just goes to show how little I understand about this. It solved it. How come it solves it when the code never even got to the print? Thank you so much. – aqueiro Nov 18 '16 at 17:55
  • 1
    @aqueiro not related to your problem, but you really should format your code properly. – Jabberwocky Nov 18 '16 at 18:04
  • It is properly formatted on my project, but when I pasted it here all indentation disappeared. So next time I should manually redo it for the submission? – aqueiro Nov 18 '16 at 18:26
  • When compiling always enable all the warnings then fix those warnings. (for `gcc` at a minimum use: `-Wall -Wextra -pedantic` I also use: `-Wconversion -std=gnu99` ) – user3629249 Nov 19 '16 at 08:38
  • never access beyond `argv[0]` without first checking `argc` to assure the command line parameter actually exists. – user3629249 Nov 19 '16 at 08:40
  • when handling an error indication returned from a system function, always print the reason the system thinks the function failed. An easy way to do that (and output the text to stderr rather than stdout) is to use the function: `perror()`. – user3629249 Nov 19 '16 at 08:42
  • for ease of readability and understanding: 1) consistently indent the code. indent after every opening brace '{' unindent before every closing brace '}'. Suggest using 4 spaces for each indent level as that is wide enough to be visible even with variable width fonts. 2) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Nov 19 '16 at 08:44
  • when calling any of the `scanf()` family of functions, When using the `%s` format specifier, always include a MAX CHARACTERS modifier that is one less than the length of the input buffer, so the user cannot overrun the buffer (which is undefined behavior and can lead to a seg fault event. – user3629249 Nov 19 '16 at 08:48
  • in the function: `ledic()` the entries in the variable `dictionary[][][]` are not initialized to any known value, so when trying to print out the first 1000 of those entries in `dictionary[5]`, If there have not been 1000 entries input, then the for() loop will try to print garbage. And that garbage may or may not have a NUL byte within the first 30 characters, so the output can source characters far beyond the current entry. This is undefined behavior. suggest using `VecOcorrencia[5] -1` for the termination value rather than 1000 – user3629249 Nov 19 '16 at 08:56
  • the variable: `dictionary[][][]` is 30*30*10000 bytes in size. I suspect that will overflow the available stack space. If you change that statement to: `static char dictionary[30][10000][30];` then it will be in the 'file space' and also have the advantage of being preset to all NUL bytes – user3629249 Nov 19 '16 at 09:02
  • the posted code does not compile due to (amongst other things) line 32 contains an extranious `}` (closing brace) – user3629249 Nov 19 '16 at 09:04

1 Answers1

3

The declaration char dictionary[30][10000][30]; creates a 9Mb variable 30*30*1000 = 9'000'000. As it is a local variable it is created on the stack and the default stack size on a typical Linux machine is only 8Mb (on Windows it's even only 1Mb).

If you declare it as static, the variable is not on the stack and therefore it can take more memory than the stacksize.

See this SO article for more details on the static keyword.

Community
  • 1
  • 1
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115