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

二维字符VLA指针异常:字符串分割函数返回后字符值变更

问题根源:局部栈内存失效导致野指针访问

你的代码核心问题出在局部数组的生命周期上:

  • 在substring_whitespace函数里,strings是栈上的二维局部数组。函数执行完毕返回时,它所在的栈帧会被销毁,这块内存会被操作系统回收或后续函数调用覆盖。
  • 你把strings[c]的地址赋值给buffer[c],相当于让main里的buffer保存了一堆指向已失效内存的野指针。所以函数返回后再访问这些指针,读取到的就是被篡改的垃圾数据。

修复方案:改用堆内存存储子串

要解决这个问题,需要为每个子串分配堆内存(用malloc),这样内存不会随函数返回而失效。修改后的代码如下:

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

size_t substring_whitespace(char* buffer[], char* string) {
    size_t initial_string_size = strlen(string) + 1;
    // 动态分配内存保存原字符串副本,避免修改输入
    char* actual_string = malloc(initial_string_size);
    if (!actual_string) {
        perror("malloc failed");
        return 0;
    }
    strcpy(actual_string, string);
    
    size_t c = 0;
    while (strlen(actual_string) > 0) {
        size_t first_whitespace_index = strcspn(actual_string, " ");
        // 为子串分配内存,+1用于存储字符串终止符
        char* substring = malloc(first_whitespace_index + 1);
        if (!substring) {
            perror("malloc failed");
            // 清理已分配内存避免泄漏
            for (size_t i = 0; i < c; i++) {
                free(buffer[i]);
            }
            free(actual_string);
            return c;
        }
        
        // 复制子串内容并添加终止符
        strncpy(substring, actual_string, first_whitespace_index);
        substring[first_whitespace_index] = '\0';
        
        // 更新剩余字符串
        size_t remaining_len = strlen(actual_string) - first_whitespace_index;
        if (remaining_len > 0 && actual_string[first_whitespace_index] == ' ') {
            // 跳过空格,移动剩余内容到字符串开头
            memmove(actual_string, actual_string + first_whitespace_index + 1, remaining_len);
        } else {
            // 无剩余内容,清空字符串
            actual_string[0] = '\0';
        }
        
        buffer[c] = substring;
        c++;
    }
    
    free(actual_string);
    return c;
}

int main() {
    char string[1000];

    fgets(string, sizeof(string), stdin);
    string[strcspn(string, "\n")] = 0;

    // 最多可能有strlen(string)+1个单词(极端情况单个字符为一个单词)
    char* buffer[strlen(string) + 1];
    size_t buffer_length = substring_whitespace(buffer, string);

    for (size_t d = 0; d < buffer_length; d++) {
        printf("\n%s", buffer[d]);
        // 使用完毕后释放内存,避免泄漏
        free(buffer[d]);
    }

    return 0;
}

额外优化说明

  1. 用malloc分配堆内存,确保子串在函数返回后依然有效。
  2. 添加内存分配失败的错误处理,避免程序崩溃。
  3. 用strncpy和memmove替代手动循环复制,代码更简洁安全。
  4. main中记得释放每个子串的内存,避免内存泄漏。
  5. 简化原代码中手动处理终止符、字符串截取的逻辑,减少出错概率。

内容的提问来源于stack exchange,提问作者Heitor E. Rezende

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:10:43