struct definition inside main() causing Segmentation Fault - c

Is it not possible to define structure inside main() .
I tried the following only to get a Segmentation Fault:
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#define TRUE 1
void main(int argc,char **argv)
{
struct test_struct
{
char test_name[50];
char summary_desc[200];
char result[50];
};
struct suite_struct
{
char suite_name[50];
struct test_struct test[500];
int test_count;
int passed;
int failed;
int unresolved;
int notrun;
}suite[500];
int a,b;
for (a=0;a<500;a++)
{
strcpy(suite[a].suite_name,"");
for (b=0;b<500;b++)
{
strcpy(suite[a].test[b].test_name,"");
strcpy(suite[a].test[b].summary_desc,"");
strcpy(suite[a].test[b].result,"");
}
suite[a].test_count=0;
suite[a].passed=0;
suite[a].failed=0;
suite[a].unresolved=0;
suite[a].notrun=0;
}
}
But the moment I take the struct definition outside it works:
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#define TRUE 1
struct test_struct
{
char test_name[50];
char summary_desc[200];
char result[50];
};
struct suite_struct
{
char suite_name[50];
struct test_struct test[500];
int test_count;
int passed;
int failed;
int unresolved;
int notrun;
}suite[500];
void main(int argc,char **argv)
{
int a,b;
for (a=0;a<500;a++)
{
strcpy(suite[a].suite_name,"");
for (b=0;b<500;b++)
{
strcpy(suite[a].test[b].test_name,"");
strcpy(suite[a].test[b].summary_desc,"");
strcpy(suite[a].test[b].result,"");
}
suite[a].test_count=0;
suite[a].passed=0;
suite[a].failed=0;
suite[a].unresolved=0;
suite[a].notrun=0;
}
}
Not sure why this is happening.
I am using the Solaris SunStudio compiler for this.

In the first example, suite lives on the stack, and in the second it lives on the data segment.
Since suite is quite large (~75MB), the segfault is almost certainly due to your program running out of stack space.
In most cases, it is best to allocate large data structures on the heap (using malloc() et al). This will also make it possible to allocate just the amount of space you require instead of always allocating space for 500 elements.

It is okay to declare a structure inside main. But in your program, the problem has got to do with the fact that you are creating 500 objects of that structure inside main function. Each object is about 15 KB in size. So, 500 objects require about 75 MB. Try printf("size: %lu\n", sizeof suite);.
You don't have that much of stack available by default. You can find the available stack using the command ulimit -s. It prints the available stack in KBs.
You can use the ulimit command to increase the stack. e.g. ulimit -s 100000.
A better approach is to dynamically allocate the memory you require using malloc().

It is legal to define a struct and to declare a local variable of that struct inside any function, including main.
But a code can be syntactically legal and crash at runtime (e.g. because it has an undefined behavior, per the C standard, or because it hits some system limitation, like a limit on the call stack).

The struct you define outside of main is global and uninitialized so it will go into the .bss segment and be initialized to 0 at the start of execution. The struct you define inside main is huge and exceeds the maximum stack size (which is about 1-2MB on Linux and probably Solaris too). Since the one outside of main is not on the stack, it appears to work in that case and not the other.

In addition to answers about stack space, malloc, and undefined behavior . . .
When I tried to compile your code, I got 3 warnings.
test.c:7:6: warning: return type of ‘main’ is not ‘int’
test.c: In function ‘main’:
test.c:32:17: warning: implicit declaration of function ‘strcpy’
test.c:32:17: warning: incompatible implicit declaration of built-in function ‘strcpy’
Return an int for main, not void.
int main(int argc,char **argv)
In C, the header for strcpy is string.h, not strings.h.

Related

How to fix function calling warnings in c?

struct reviewStruct {
char reviewer[MAX_STR];
int feedback[NUMBER_MOVIES];
};
int readMovies(FILE *file, char movieNames[NUMBER_MOVIES][MAX_STR])
int readReviews(FILE *file, struct reviewStruct reviews[NUMBER_REVIEWERS])
int main() {
FILE *file;
char movieNames[NUMBER_MOVIES][MAX_STR];
char reviews [NUMBER_REVIEWERS];
myFile("cisfile.txt");
readMovies(file, movieNames);
readReviews(file, reviews);
}
This is my main function along with the function definitions, when I compile the program I get the following errors:
"warning: passing argument 2 of ‘readReviews’ from incompatible pointer type" for the line: "readReviews(file, reviews);"
"warning: ‘file’ is used uninitialized in this function" for the line: "readMovies(file, movieNames);"
How do I fix these two errors?
I took your code and tried to make it run.
#include <stdio.h>
#include <stdlib.h>
#define MAX_STR 10
#define NUMBER_MOVIES 3
#define NUMBER_REVIEWERS 2
struct reviewStruct {
char reviewer[MAX_STR];
int feedback[NUMBER_MOVIES];
};
int readMovies(FILE *file, char movieNames[NUMBER_MOVIES][MAX_STR])
{
printf("hi\n");
}
int readReviews(FILE *file, void *reviews)
{
printf("bye\n");
}
int main(void)
{
FILE *myFile;
char movieNames[NUMBER_MOVIES][MAX_STR];
char reviews [NUMBER_REVIEWERS];
myFile = fopen("cisfile.txt","r");
readMovies(myFile, movieNames);
readReviews(myFile, reviews);
fclose(myFile);
return 0;
}
With these assumptions runs without any warnings.
I am using gcc 8.3.0 without any options.
1. First warning:
As per what #kaylum said. You are declaring char reviews[MUMBER_REVIEWERS], but when you defined the parameters for your function: int readReviews(FILE *file, struct reviewStruct reviews[NUMBER_REVIEWERS], it is clear that the parameter concerned by the array should be of type struct reviewStruct.
So in the line where you got the warning change: char reviews [NUMBER_REVIEWERS]; to struct reviewStruct reviews[NUMBER_REVIEWERS];. That should be a pointer to a structure type, not a pointer to a character type. Or if you want to go more in detail: It is a pointer to an array of structures, the type of the array is determined by the type of elements it holds.
2. Second warning:
Now let's take a look at the second warning: warning: ‘file’ is used uninitialized in this function" for the line: "readMovies(file, movieNames)
As the warning says. Your pointer file was not initialized. Take it as a rule, that you cannot use a pointer without initializing it to something to point to. I believe that you are trying to read from a stream. So just in case you need it, you perhaps may be willing to use the function fopen(), which returns a pointer to a stream.

Segmentation fault in C, can't figure why

I have a function that is supposed to read (in a very bad way) a file. I expect it to modify a struct that I pass as a parameter to store the things that it has to read. But when I call it, it throws a segmentation fault. I have a print as the first thing the function does, and it doesn't do it. So I guess I have a problem with the declaration of the function or something. I can't figure it out.
int main(int argc, char **argv){
//some parser here
struct client_config *config;
read_software_config_file(*config); //I also passed it as non pointer and & but nothing worked.
}
void read_software_config_file(struct client_config config){
printf("Hello"); //it breaks here
}
As someone pointed out I did this:
struct client_config config;
read_software_config_file(&config);
But it still shows me segmentation fault.
Here is a working example:
#include <stdio.h>
struct client_config
{
int data;
};
void read_software_config_file(struct client_config *config); // Forward Declaration
int main(int argc, char **argv)
{
struct client_config config; // Memory on stack. Use malloc/calloc for heap
config.data = 10; // Init data
read_software_config_file(&config);
printf("config.data = %d\n", config.data);
return 0;
}
void read_software_config_file(struct client_config *config)
{
printf("Hello\n");
config->data = 12;
}
I would generally advise to compile with -Wall -Wextra -pedantic to catch errors early.
You have to forward declare the function read_software_config_file (or include a header etc.) s.t. the compiler knows the signature when you call it in main.
As said in the comments you should take a pointer to the struct, s.t. it can be modified.
The output after running main is:
Hello
config.data = 12
When you declare any variable, pointer or not, without initializing it, it gets whatever is in memory as its current value. Some higher level languages may implicitly initialize all new values with "default" variables. You may have gotten used to this from previous programming experience; this is not the case in C.
If you use the * dereference operator on an uninitialized pointer, you are dereferencing whatever address is represented by the current value of the pointer, which is undefined behavior, and almost certainly going to cause an access violation.
You need to initialize your pointer to point to something; either an existing struct client_config, or new heap memory allocated with malloc or calloc.
Also, if your function really is meant to take a pointer to a struct client_config, the parameter should have a * operator on it as well.

c max array size effected by printf

I would like to know why some of these programs are throwing a segfault while others aren't.
This program throws a segfault:
#include <stdio.h>
int main(){
int ar[2096263];
printf("asdf");
}
This one doesn't:
#include <stdio.h>
int main(){
int ar[2096263];
}
This program doesn't:
#include <stdio.h>
int main(){
int ar[2096262];
printf("asdf");
}
This one does:
#include <stdio.h>
int main(){
int ar[2096262];
printf("asdf");
printf("asdf");
printf("asdf");
printf("asdf");
printf("asdf");
}
this one doesn't:
#include <stdio.h>
int main(){
int ar[2096262];
printf("asdf");
printf("asdf");
printf("asdf");
printf("asdf");
}
I don't understand why calling printf changes the limit on the size of the array I can have in main. Also, Why can't I have more than 2096262 ints in an array?
Thanks
Due to implementation reasons local variables, including arrays, are stored on the stack. Function calls also add to the stack, both with some meta-information but also with the called functions local variables. It all adds up.
Now, the stack is a limited resource, for example on Windows the default process stack size is only a single MB.
On Linux (which I assume you use since you mention "segmentation fault") the default stack size is 8MB, and with two million four-byte integers on the stack (sizeof(int) is usually 4) you hit that limit and have a stack overflow.
You have declare locally. Local array store in stack section of memory and size of the stack is limited.so, when you give size more than stack, you get segmentation fault. It's also called stack overflow problem.
To have larger arrays, you need to either declare it as a static variable or in file scope.
static int ar[2096263]; // This works fine.

C - Global vs Local multidimensional array

When I execute this code (gcc compiled):
#include <stdio.h>
int main() {
int table[1005][1005];
return 0;
}
it stops working, but when I change it to:
#include <stdio.h>
int table[1005][1005];
int main() {
return 0;
}
it works just fine.. Why is this concretely happening? Does global variables get more space to allocate? Why?
First way is probably creating the array on the stack, the second is probably putting it into the "data segment".
The amount allocated may be too big for the stack depending on your platform.

How to pointer reference dynamic sized pointer to array?

I want to be able to reference variable sized array with a global pointer. But what kind of pointer do I use that will work with variable sizes of the array? In the example below, assume N will only be known at runtime (could be an argument for example) so compile time solutions won't work.
What I want to achieve:
main.c
some_sort_of_pointer *x;
main()
{
int N=256; //or N=64 or whatever
char (*LC)[N];
LC=malloc(1024);
x=LC;
memcpy(x[2],"hello world",11);
x[0][176]=123;
dostuff();
}
I'm sure there's an easy obvious way to do this but I can't seem to nail it. My first attempt at asking this was a mess so this time I'm hoping it's clear what I want to achieve.
OS Centos 6.5
compiler GCC 4.8 (using C99)
As at compile time the type to be referenced isn't given, a void pointer might help.
However only storing an untyped reference (what void * in fact is is) is not enough, as it is essential to also know the size of the (VL)array. So the latter also needs to be stored globally, as it can not be pulled from the memory referenced.
An example how this can be achieve is given below:
main.h:
#include <stdlib.h> /* for size_t */
struct VLA_descriptor
{
void * p;
size_t s;
}
extern struct VLA_descriptor vla_descriptor;
foo.h:
void foo(void);
foo.c:
#include "main.h"
#include "foo.h
void foo(void)
{
char (*p)[vla_descriptor.s] = vla_descriptor.p;
/* Do something with the VLA reference p. */
}
main.c:
#include "main.h"
#include "foo.h"
struct VLA_descriptor vla_descriptor = {0};
int main(int argc, char ** argv)
{
size_t s = atoi(argv[1]);
char (*p)[s] = malloc(s);
vla_descriptor.p = p;
vla_descriptor.s = s;
foo();
... /* Free stuff and return. */
}
Error checking had been omitted in this example's code for the sake of readability.
With much thanks to #alk (and everyone else who responded) I think I have the closest I'm going to get to what I'm looking for:
void *LC
int LCS;
int main(int argc, char **argv) {
LCS=256;
LC=malloc(1024)
memcpy(((char(*)[LCS])LC)[2],"hello world",11);
((char(*)[LCS])LC)[0][176]=123;
printf("%d %s\n",((char(*)[LCS])LC)[0][176],&((char(*)[LCS])LC)[2]);
}
((char(*)[LCS])LC) is the equivalent of a what I wanted. It's similar to #alk's idea and does require 2 globals but it means I can use it in functions without having to declare a new variable. I've credited #alk with the answer as what he posted gave me 90% of what I needed.
Though if anyone can reduce ((char(*)[LCS])LC) to a single global, I would be excited to see it :)

Resources