определение структуры внутри main (), вызывающее ошибку сегментации - PullRequest
3 голосов
/ 25 января 2012

Разве невозможно определить структуру внутри main (). Я попробовал следующее только для того, чтобы получить ошибку сегментации:

#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;
        }
}

Но в тот момент, когда я выношу определение структуры за пределы его действия:

#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;
        }
}

Не уверен, почему это происходит. Для этого я использую компилятор Solaris SunStudio.

Ответы [ 5 ]

6 голосов
/ 25 января 2012

В первом примере suite живет в стеке, а во втором - в сегменте данных.

Так как suite довольно большой (~ 75 МБ), segfault почти навернякаиз-за того, что вашей программе не хватает места в стеке.

В большинстве случаев лучше всего выделять большие структуры данных в куче (используя malloc() и др.).Это также позволит выделить только необходимое количество места вместо того, чтобы всегда выделять место для 500 элементов.

3 голосов
/ 25 января 2012

Можно объявить структуру внутри main.Но в вашей программе проблема связана с тем, что вы создаете 500 объектов этой структуры внутри основной функции.Каждый объект имеет размер около 15 КБ.Итак, 500 объектов требуют около 75 МБ.Попробуйте printf("size: %lu\n", sizeof suite);.

По умолчанию у вас не так много стека.Вы можете найти доступный стек, используя команду ulimit -s.Он печатает доступный стек в килобайтах.

Вы можете использовать команду ulimit для увеличения стека.например, ulimit -s 100000.

Лучшим подходом является динамическое выделение необходимой памяти с помощью malloc().

1 голос
/ 25 января 2012

В дополнение к ответам о стековом пространстве, malloc и неопределенном поведении.,.

Когда я пытался скомпилировать ваш код, я получил 3 предупреждения.

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’

Возвращает int для main, а не void.

int main(int argc,char **argv)

В C,заголовок для strcpy - это string.h, а не strings.h.

1 голос
/ 25 января 2012

Структура, которую вы определяете вне main, является глобальной и неинициализированной, поэтому она войдет в сегмент .bss и будет инициализирована в 0 в начале выполнения.Структура, которую вы определяете внутри main, огромна и превышает максимальный размер стека (который составляет около 1-2 МБ в Linux и, вероятно, в Solaris).Так как один вне main не находится в стеке, он, кажется, работает в этом случае, а не другой.

1 голос
/ 25 января 2012

Допустимо определить struct и объявить локальную переменную этого struct внутри любой функции, включая main.

Но код может быть синтаксически допустимым и аварийно завершаться во время выполнения (например, из-за того, что он имеет неопределенное поведение, в соответствии со стандартом C, или потому что он достигает некоторого системного ограничения, такого как ограничение в стеке вызовов).

...