You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言动态数组结果随机异常:未改代码却输出不稳定问题求助

动态数组存储单词索引时结果不稳定的问题分析与修复

问题重现

你实现了C语言动态数组,用于存储字符串中匹配单词的起始索引,但调用findWord("hello, world, hello", "hello")时,结果有时正确有时错误,核心是存储的指针指向无效内存,触发未定义行为。

你的代码片段

动态数组结构体定义

typedef void (*PrintArrayElement)(const void* element);

typedef struct {
    size_t size;
    size_t capacity;
    void** array;
    PrintArrayElement printElement;  // Callback
} dynamic_array;

添加元素函数

void arrayAddItem(dynamic_array* container, void* item)
{
    if (container->size == container->capacity)
    {
        void** temp = container->array;
        container->capacity <<= 1;
        container->array = (void **)realloc(container->array, container->capacity * sizeof(void*));
        if (!container->array)
        {
            printf("Out of Memory\n");
            container->array = temp;
            return;
        }
    }
    container->array[container->size] = strdup(item);
    container->size++;
}

查找单词索引函数

dynamic_array* findWord(char str[], char keyword[])
{
    dynamic_array* indexes;
    arrayInit(&indexes, 16, printInt);
    int i = 0;
    int start = 0;
    int end = 0;
    size_t len = strlen(str);
    while (i < len) {
        while (i < len && !isalpha(str[i]))
        {
            i++;
        }
        if (isalpha(str[i]))
        {
            start = i;
            while (i < len && isalpha(str[i]))
            {
                i++;
            }
            end = i;
            char* word = (char*)malloc(end - start + 1);
            strncpy(word, &str[start], end - start);
            word[end - start] = '\0';
            if(strcmp(word, keyword) == 0)
            {
                printf("%d\n", start);
                arrayAddItem(indexes, &start);
            }
            free(word);
        }
    }
    return indexes;
}

问题根源

  1. 错误使用strdup:strdup是字符串专用的复制函数,会从传入的char*指针开始复制直到遇到'\0'。但你传入的是&start(int变量的地址),strdup会把这个地址当成char*读取内存,而int变量后不一定有'\0',这会导致内存越界读取,复制的内容完全不可控,触发未定义行为——这就是结果时对时错的核心原因。

  2. 存储局部变量地址:start是findWord函数的局部变量,每次循环都会被覆盖,函数执行结束后局部变量的内存会被释放。你把&start存入动态数组,相当于存储了一个野指针,后续访问时内存内容可能已被其他操作覆盖,导致读取到错误值。

修复方案

1. 修改arrayAddItem函数,正确存储任意类型元素

替换错误的strdup为通用的内存分配+值复制逻辑,让函数支持任意类型的元素存储:

void arrayAddItem(dynamic_array* container, void* item, size_t item_size)
{
    if (container->size == container->capacity)
    {
        void** temp = container->array;
        container->capacity <<= 1;
        // 去掉不必要的强制类型转换,realloc返回void*可直接赋值
        container->array = realloc(container->array, container->capacity * sizeof(void*));
        if (!container->array)
        {
            printf("Out of Memory\n");
            container->array = temp;
            return;
        }
    }
    // 为当前元素分配独立内存,复制传入的值
    void* elem = malloc(item_size);
    if (!elem) {
        printf("Out of Memory\n");
        return;
    }
    memcpy(elem, item, item_size);
    container->array[container->size] = elem;
    container->size++;
}

2. 修复findWord函数的两处问题

  • 调用arrayAddItem时传入元素大小sizeof(int);
  • 避免越界访问str[i],先检查i < len再判断字符类型:
dynamic_array* findWord(char str[], char keyword[])
{
    dynamic_array* indexes;
    arrayInit(&indexes, 16, printInt);
    int i = 0;
    int start = 0;
    int end = 0;
    size_t len = strlen(str);
    while (i < len) {
        while (i < len && !isalpha(str[i]))
        {
            i++;
        }
        // 先判断i是否越界,再检查字符类型
        if (i < len && isalpha(str[i]))
        {
            start = i;
            while (i < len && isalpha(str[i]))
            {
                i++;
            }
            end = i;
            char* word = (char*)malloc(end - start + 1);
            strncpy(word, &str[start], end - start);
            word[end - start] = '\0';
            if(strcmp(word, keyword) == 0)
            {
                printf("%d\n", start);
                // 传入元素大小,正确存储int值
                arrayAddItem(indexes, &start, sizeof(int));
            }
            free(word);
        }
    }
    return indexes;
}

3. 补充动态数组销毁函数(避免内存泄漏)

记得实现销毁函数,遍历释放每个元素的内存,再释放数组本身:

void arrayDestroy(dynamic_array* container)
{
    if (!container) return;
    for (size_t i = 0; i < container->size; i++) {
        free(container->array[i]);
    }
    free(container->array);
    free(container);
}

验证

修改后调用findWord("hello, world, hello", "hello"),动态数组会存储两个独立分配的int内存块,分别保存0和14,访问时不会出现野指针或越界问题,结果稳定。

内容的提问来源于stack exchange,提问作者somerandomname

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:24:55