DIY Remover не работает, что я делаю не так?(Неверное чтение размера 1, сегфоут) - PullRequest
0 голосов
/ 18 февраля 2019
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *delete_comments(char *input) {
    unsigned int i = 0;
    unsigned int a = 0;

    char* dest = malloc(    (strlen(input) + 1) * sizeof(char)  );

    while (i < strlen(input)) {
         if(input[i] == '/' && input[i + 1] == '/') {
            while (input[i - 1] != '\n') {
            }         
         }
         else if (input[i] == '/' && input[i+1] == '*') {
            while (input[i-1] != '*' || input[i] != '/') {
                i++;
            }
         }

         dest[a] = input[i];
         i++;
         a++;
    }

    free(input); 
    return dest;
}

Журнал сборки:

make -C test valgrind
make[1]: Entering directory '/home/agent/test'
sed -e 's/int[ \t]\{1,\}main[ \t]*[(]/int _no_main(/g;s/void[ \t]\{1,\}main[ \t]*[(]/void _no_main(/g;s/^main[ \t]*[(]/_no_main(/g' ../src/source.c >../src/source.c.nomain.c
gcc -pthread -g -Wall -Wvla -std=c99 -o test test_source.c tmc-check.c checkhelp.c ../src/source.c.nomain.c -lcheck_pic -pthread -lrt -lm -lsubunit
valgrind -q --log-file=valgrind.log --track-origins=yes --leak-check=yes ./test
Running suite(s): Test-08_cleaner
0%: Checks: 1, Failures: 0, Errors: 1
test_source.c:67:E:test_delete_comments:test_delete_comments:0: (after this point) Received signal 11 (Segmentation fault)
make[1]: Leaving directory '/home/agent/test'

Valgrind output:
==44== Invalid read of size 1
==44==    at 0x402FB9: delete_comments (source.c.nomain.c:19)
==44==    by 0x401E3D: test_delete_comments (test_source.c:74)
==44==    by 0x406DE2: srunner_run (in /home/agent/test/test)
==44==    by 0x402492: tmc_run_tests (tmc-check.c:134)
==44==    by 0x402127: main (test_source.c:206)
==44==  Address 0x105b3cc4f is not stack'd, malloc'd or (recently) free'd
==44== 
==44== 
==44== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==44==  Access not within mapped region at address 0x105B3CC4F
==44==    at 0x402FB9: delete_comments (source.c.nomain.c:19)
==44==    by 0x401E3D: test_delete_comments (test_source.c:74)
==44==    by 0x406DE2: srunner_run (in /home/agent/test/test)
==44==    by 0x402492: tmc_run_tests (tmc-check.c:134)
==44==    by 0x402127: main (test_source.c:206)
==44==  If you believe this happened as a result of a stack
==44==  overflow in your program's main thread (unlikely but
==44==  possible), you can try to increase the size of the
==44==  main thread stack using the --main-stacksize= flag.
==44==  The main thread stack size used in this run was 2048000

Итак, вот код и отчет valgrind.Что я делаю неправильно?Это код для удаления комментариев, написанный на языке C. Я пытался просмотреть прежние темы о недопустимом размере чтения и segfault, но на самом деле я не разбирался в своей проблеме.я знаю, что слишком мало памяти, если какие-либо комментарии удалены, но я не думаю, что это должно вызывать проблемы, если это?.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Segfault происходит здесь:

while (input[i - 1] != '\n') ...

Ваш счетчик i является беззнаковым int.В начале у вас есть i == 0 и i - 1 - это очень большое число, вероятно, 2³² - 1. Это может привести к segfault.

Обратите внимание, что Valgrind говорит, что адрес не был "stack'd,malloc'd».Обычно, если вы выходите за границы массива, он говорит, что адрес, вызывающий сбой, - это «один байт вне памяти malloc'd» или что-то подобное.

Использование беззнаковых целочисленных значений в качестве счетчиков - хороший выбор, ноосторожно, когда вы идете назад.В вашем случае вам вообще не нужно оглядываться назад: вы должны выйти за пределы //, а затем двигаться вперед столько, сколько потребуется.

В качестве отступления: проверка на strlen() в циклеусловие не очень хорошая идея в C, потому что strlen обходит всю строку и ищет нулевой терминатор.Умный компилятор может оптимизировать это, но лучше рассчитать длину строки один раз или, может быть, лучше, проверить, является ли `input [i]! = '\ 0'.

Завершающий ноль - это то, что вам нужноучитывать при пропуске символов с отрицательным условием тоже.Например, недостаточно проверить, является ли текущий символ новой строкой.Вы также должны убедиться, что это не нулевой терминатор:

while (input[i] && input[i] != '\n') i++;
0 голосов
/ 18 февраля 2019

У вас есть вечный цикл в

        while (input[i - 1] != '\n') {
        }

Это никуда не денется.По крайней мере, вам нужно обновлять переменную цикла i в каждой итерации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...