是否可以可靠地检测到realloc的误用?

时间:2018-02-07 10:33:32

标签: c realloc

看来当使用指向非堆内存的指针调用realloc函数时,程序就会死掉

Error(s):
Invalid memory reference (SIGSEGV)

我的str_cat函数是否可以检测到这种情况,从而避免调用realloc

这是一个演示问题的示例程序:

//gcc 5.4.0

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

int str_cat(char *dest, size_t *dest_size, char *src);

int str_cat(char *dest, size_t *dest_size, char *src) {
// if there is sufficient free space in the dest buffer, append src, 
// otherwise keep doubling the allocated size of dest until it is large 
// enough to append src        
    size_t src_len = strlen(src);
    size_t dest_len = strlen(dest);
    if (src_len < *dest_size - dest_len) {
        memcpy(dest+dest_len, src, src_len+1);
        return 0;
    } else {
        char *new_dest = NULL;
        size_t new_size = *dest_size * 2;
        while (src_len >= new_size - dest_len) {
            new_size *= 2;
        }
        if ((new_dest = realloc(dest, new_size)) != NULL) {
           dest = new_dest;
           *dest_size = new_size;
           memcpy(dest+dest_len, src, src_len+1);  
           return 0;
        } else {
            return -1;
        }
    }
}

int main(void)
{
    size_t heap_buf_size=5;
    char *heap_buf = malloc(heap_buf_size);
    size_t stack_buf_size=5;
    char stack_buf[stack_buf_size];

    *heap_buf = '\0';
    if (str_cat(heap_buf, &heap_buf_size, "foo")) return -1;
    printf("1. heap_buf %s\n", heap_buf);
    printf("1. heap_buf_size %zu\n", heap_buf_size);
    if (str_cat(heap_buf, &heap_buf_size, "bar")) return -1;
    printf("2. heap_buf %s\n", heap_buf);
    printf("2. heap_buf_size %zu\n", heap_buf_size);

    stack_buf[0] = '\0';
    if (str_cat(stack_buf, &stack_buf_size, "foo")) return -1;
    printf("3. stack_buf %s\n", stack_buf);
    printf("3. stack_buf_size %zu\n", stack_buf_size);
/* If the line below is uncommented, the program dies
   with Invalid memory reference (SIGSEGV)    */
//    if (str_cat(stack_buf, &stack_buf_size, "bar")) return -1;
    printf("4. stack_buf %s\n", stack_buf);
    printf("4. stack_buf_size %zu\n", stack_buf_size);

    return 0;
}

1 个答案:

答案 0 :(得分:4)

不,在大多数系统上以有意义的方式捕获或处理SIGSEGV是不可能的。这是因为在程序导致未映射的内存访问时,它可能已经损坏了它的堆栈或数据或代码,因此无法信任并且无法保存。如果您发现这种情况,最好立即崩溃,这样您就可以在调试器中分析转储核心。

要跟踪无效访问,valgrind是一个不错的工具,尝试valgrind ./a.out,运行缓慢但跟踪很多事情,包括误用malloc / realloc / free。

编辑:(因为OP编辑了问题)不,除非你跟踪所有(de)分配(比如使用malloc钩子),否则无法检测指针是否是realloc / free的正确参数。