簡體   English   中英

在valgrind下運行時讀取無效

[英]Invalid read when running under valgrind

gcc (GCC) 4.7.2
valgrind-3.8.1
c89

你好,

==1160== Invalid read of size 1
==1160==    at 0x8048C94: get_input_values (parse_cmd_input.c:278)
==1160==    by 0x8048BA0: parse_input (parse_cmd_input.c:245)
==1160==    by 0x80489A1: main (parse_cmd_input.c:50)
==1160==  Address 0x40ef02c is 0 bytes after a block of size 4 alloc'd
==1160==    at 0x40072C5: calloc (vg_replace_malloc.c:593)
==1160==    by 0x8048B28: parse_input (parse_cmd_input.c:239)
==1160==    by 0x80489A1: main (parse_cmd_input.c:50)

因此,其說法是該地址正在讀取分配大小為4的零字節,並試圖從中讀取1字節。 但是,我還沒有超出數組的范圍,我正在訪問元素0。

我已經檢查了gdb,並且元素零包含一個字符。

我的程序不會崩潰,並且看起來可以正常工作。 但這可能會在生產服務器上引起問題。

我不確定在這里是否正確:這應該是:

cpy_input = calloc(strlen(input) + 1, sizeof(char*));

要么:

cpy_input = calloc(strlen(input) + 1, sizeof(char));

在我的系統上,一個char是1個字節,而指向char的指針是4個字節。

傳入的字符串將類似於"25 b"

int parse_input(const char *input)
{
    char *cpy_input = NULL;
    int has_error = -1;

    if(strlen(input) == 0) {
        LOG_ERR("FAILED: Empty string");
        return -1;
    }

    cpy_input = calloc(strlen(input) + 1, sizeof(char));

    apr_cpystrn(cpy_input, input, sizeof(cpy_input));
    LOG_INFO("[ %s ]", cpy_input);

    memset(&channel, 0, sizeof channel);
    has_error = get_input_values(cpy_input, &channel);

    free(cpy_input);

    return has_error;
}


int get_input_values(const char *str, channel_t *channel)
{
    size_t i = 0;
    size_t k = 0;
    int upper_flag = 0;

    /* Indicates no digits or command found*/
    channel->lower = -1;
    channel->upper = -1;
    channel->cmd = -1;

#define DIG_BUFFER_SIZE 32
    char dig_buffer_lower[DIG_BUFFER_SIZE];
    char dig_buffer_upper[DIG_BUFFER_SIZE];

    if(strlen(str) == 0) {
        LOG_ERR("FAILED: Empty string");
        return -1;
    }

    memset(dig_buffer_lower, 0, DIG_BUFFER_SIZE);
    memset(dig_buffer_upper, 0, DIG_BUFFER_SIZE);

    LOG_INFO("SIZE %d %d", sizeof(char), sizeof(char*));

    /* Increament and check for digits */
    for(i = 0; i < DIG_BUFFER_SIZE; i++) {
    switch(str[i]) {
        case 32: /* ignore space */
            continue;

        case 45: /* '-' Start upper bounds */
            LOG_DEBUG("Found a '-' check upper value");
            /* Having a second '-' means the string is invalid */
            if(!upper_flag) {
                upper_flag = 1;
                k = 0;
            }
            break;

        } /* switch */

        /* Insert on digits into the lower and upper values */
    if(isdigit(str[i])) {
            if(upper_flag) {
                dig_buffer_upper[k++] = str[i];
                LOG_DEBUG("dig_buffer_upper[%d] %s", i, dig_buffer_upper);
            }
            else {
                /* Add to digit buffer */
                dig_buffer_lower[k++] = str[i];
                LOG_DEBUG("dig_buffer_lower[%d] %s", i, dig_buffer_lower);
            }
        }
    } /* for loop */

非常感謝您的任何建議,

sizeof(cpy_input)只是sizeof(char *) ,而不是字符串長度。 相反,說:

apr_cpystrn(cpy_input, input, strlen(input) + 1);

或更妙的是,使用裸露的strcpy或等效strcpy 同樣,也不需要使用calloc將數組歸零,因為無論如何您都將要覆蓋它。 並且由於sizeof(char)根據定義為1 ,因此您可以使用以下方式分配數組:

cpy_input = malloc(strlen(input) + 1);

(請仔細考慮一下字符串:您已經被擺在明智的位置使用null終止符的擺布,否則strlen將會崩潰或返回巨大的值。一旦您信任strlen的結果,就可以保證分配足夠的空間內存strcpy字符串和空終止符。另外,您也可以使用memcpy一個甚至可能更有效的復制,因為你知道的大小)。

好的,也許我丟失了一些東西,但是您的for循環將迭代0 .. DIG_BUFFER_SIZE-1 ,從str[i]讀取。 我看不到是什么原因會導致該循環提早中斷,尤其是因為它似乎立即包裹了一個switch ,因此該switch內部的任何break都將退出該switch ,但不會退出for

您的calloc(strlen(input) + 1, sizeof(char)); 為輸入的確切長度正確分配存儲空間。 如果字符串短於DIG_BUFFER_SIZE ,則get_input_values中的下游代碼似乎不會停止。

(我很樂意被證明是錯誤的,但是要知道,我們需要查看更多代碼。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM