C: Ошибка шины при использовании разных аргументов компиляции

Итак, это третья неделя моей жизни на C, и мне поручили написать программу, которая принимает до 100 слов длиной до 80 символов, вычисляет среднюю длину входных данных, печатает слова большего размера, чем в среднем, и наконец печатает средний размер слова. EDIT: мы также должны использовать emalloc, метод рекурсивного вывода, и освободить всю используемую память.

Успех! ... или я так думал.

Я написал следующее в Eclipse, который использует gcc -E -P -v -dD в качестве аргументов компиляции, и я не получаю ошибок времени выполнения при запуске программы с использованием предоставленных тестовых примеров.

Теперь я завершил код, который должен воспроизвести в течение 30-минутного практического занятия. Нам говорят, что мы должны использовать текстовый редактор и что gcc -W -Wall -ansi -pedantic нужно будет использовать в качестве аргументов компиляции, но если я вместо этого использую эти аргументы, это означает, что моя программа всегда завершается с ошибкой шины.

РЕДАКТИРОВАТЬ: исправлено и отформатировано

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

#define MAXIMUM_STRING_LENGTH 80
#define MAXIMUM_ARRAY_LENGTH 100

void* memory_allocation(size_t sizeof_memory_required) {

    void* free_memory_pointer = malloc(sizeof_memory_required);

    if (free_memory_pointer/*exists*/) {
        return free_memory_pointer;
    } else {
        fprintf(stderr, "*** MEMORY ALLOCATION FAILURE ***\n");
        exit(EXIT_FAILURE);
    }
}

void print_larger_than_average_strings(char** string_pointers, int i, const double AVERAGE_STRING_LENGTH) {

    if (string_pointers[i]/*exist*/) {
        if (strlen(string_pointers[i]) > AVERAGE_STRING_LENGTH) {
            printf("%s\n", string_pointers[i]);
        }
        print_larger_than_average_strings(string_pointers, ++i, AVERAGE_STRING_LENGTH);
    } else {
        fprintf(stderr, "%.2f\n", AVERAGE_STRING_LENGTH);
    }
}

int main(void) {

    int string_count = 0;
    char string[MAXIMUM_STRING_LENGTH];
    char* string_pointer[MAXIMUM_ARRAY_LENGTH];
    int i;
    double character_count;

    while ((string_count < MAXIMUM_ARRAY_LENGTH) && (1 == scanf("%79s", string))) {
        string_pointer[string_count] = memory_allocation(sizeof string_pointer[0][0] * (strlen(string) + 1));
        strcpy(string_pointer[string_count++], string);
    }
    string_pointer[string_count] = NULL;
    for (i = 0; i < string_count; i++) {
        character_count += strlen(string_pointer[i]);
    }
    if (string_count/*exists*/) {
        print_larger_than_average_strings(string_pointer, 0, character_count / string_count);
        for (i = 0; i < string_count; i++) {
            free(string_pointer[i]);
        }
    }
    return EXIT_SUCCESS;
}

person Community    schedule 03.08.2009    source источник
comment
Вы должны форматировать свой код немного лучше, чтобы начать с   -  person Aamir    schedule 03.08.2009
comment
Я переформатировал его, чтобы сделать его немного лучше для моих глаз и мозга.   -  person Aamir    schedule 03.08.2009
comment
В качестве общего совета по отладке: попробуйте добавить несколько отпечатков в свой код и посмотрите, что получится.   -  person Makis    schedule 03.08.2009
comment
@Sudo: я не думаю, что изменения форматирования должны были быть отменены. Правильно отформатированный код привлечет больше внимания к вашему вопросу, и у вас будет больше шансов получить лучший ответ.   -  person Aamir    schedule 03.08.2009
comment
@sudo: компилятор может легко читать код в любом формате. Вам следует взять за правило форматировать исходный код, чтобы его другие люди могли легко читать. То, что вы показываете здесь, не подходит. Имейте в виду, мне не очень нравится соглашение BSD, которое использовал Аамир, и я действительно предпочитаю стиль One True Brace. Но любой из них лучше воспринимается, чем беспорядок, который у вас здесь...   -  person dmckee --- ex-moderator kitten    schedule 03.08.2009


Ответы (3)


У вас неправильное «условие остановки» в рекурсивной функции «o». Он проверяет if(wpp[i]), но последний элемент этого массива не инициализируется значением NULL. Вы должны: изменить "char *wp[100]" на "char *wp[101]; wp[100]=NULL;". Тогда это должно работать, но это все еще не очень красивый фрагмент кода.

person Pawel Kolodziej    schedule 03.08.2009
comment
PS. вы также должны иметь wp[wc]=NULL; непосредственно перед for(...) в main(); - person Pawel Kolodziej; 03.08.2009

Условие завершения вашей рекурсивной функции o нарушено. Массив строк не завершается нулем, почему это должно быть? Почему бы просто не использовать там простую for вместо рекурсивной функции? Что-то типа:

for(i=0;i<wc;i++) {
      if(strlen(wpp[i])>av)
         printf("%s\n",wpp[i]); 
 }

Вот как я узнал, используя gdb:

t@c:~/tmp$ gcc -g -Wall -W -ansi -pedantic  test.c                      
t@c:~/tmp$ gdb ./a.out 
GNU gdb 6.8-debian                  
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.           
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) r
Starting program: /home/tudor/tmp/a.out
sdafasd
sadsa
sasaaaaaaaa
saaaaaaaaaa
asss
sasaaaaaaaa
saaaaaaaaaa

Program received signal SIGSEGV, Segmentation fault.
0xb7eba1e3 in strlen () from /lib/i686/cmov/libc.so.6
(gdb) bt
#0  0xb7eba1e3 in strlen () from /lib/i686/cmov/libc.so.6
#1  0x08048618 in o (wpp=0xbffad51c, av=7.5999999999999996, i=5) at test.c:13
#2  0x08048662 in o (wpp=0xbffad51c, av=7.5999999999999996, i=5) at test.c:14
#3  0x08048662 in o (wpp=0xbffad51c, av=7.5999999999999996, i=4) at test.c:14
#4  0x08048662 in o (wpp=0xbffad51c, av=7.5999999999999996, i=3) at test.c:14
#5  0x08048662 in o (wpp=0xbffad51c, av=7.5999999999999996, i=2) at test.c:14
#6  0x08048662 in o (wpp=0xbffad51c, av=7.5999999999999996, i=1) at test.c:14
#7  0x0804876c in main () at test.c:25
(gdb) frame 1
#1  0x08048618 in o (wpp=0xbffad51c, av=7.5999999999999996, i=5) at test.c:13
13              if(strlen(wpp[i])>av)printf("%s\n",wpp[i]);
(gdb) p i
$1 = 5
(gdb) p wpp
$2 = (char **) 0xbffad51c
(gdb) p *wpp[i]
Cannot access memory at address 0x8
person tsg    schedule 03.08.2009

В вашей рекурсивной функции с именем o нет условия завершения. Вы должны как-то остановить рекурсию.

Попробуйте этот код без рекурсии:

void* AllocateMemory(size_t s)
{
    void* mp = malloc(s);
    if(mp)
        return mp;
    else 
    {
        fprintf(stderr,"MALLOC FAILED!\n");
        exit(1);
    }
}

void PrintLargerWords(const char* wpp, double av)
{
    if(wpp)
    {
        if(strlen(wpp) > av)
            printf("%s\n",wpp);
    }
    else 
        fprintf(stderr,"%.2f\n",av);
}

int main(void)
{
    char w[80];
    char* wp[100];
    int wc=0;
    double cc=0;
    while(wc<5 && 1==scanf("%79s",w))
    {
        int length = strlen(w);
        wp[wc]= (char*)AllocateMemory((length+1) * sizeof(wp[0][0]));
        strcpy(wp[wc++],w);
        cc += length;
    }
    for(int j = 0; j<wc; j++)
    {
        PrintLargerWords(wp[j],cc/wc);
    }
    for(int i=0; i<wc; i++)
        free(wp[i]);
    return 0;
}

Я не коснулся большей части вашего кода. Также выполните правильную проверку ошибок.

person Aamir    schedule 03.08.2009