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

Malloc分配内存异常:硬编码分配2字符却仅分配1字符致段错误

问题:字符串追加函数的段错误与内存分配异常

我实现了一个appendCharacterToString函数,接收char数组指针string(按引用传递)、char类型字符character(按值传递)、unsigned short int类型变量length(按引用传递)。函数逻辑为:若string已分配内存,则重新分配为(*length + 2)*sizeof(char)大小,将length加1,最后两个字符分别设为character和空终止符;若string未分配,则分配2*sizeof(char)大小的内存,再初始化字符。但设置索引为length的最后一个字符时发生段错误。

原函数代码

void appendCharacterToString(char** string, char character, unsigned short int * length) {

    if (*string != NULL) {
        *string = (char* ) realloc(*string, (*length + 2) * sizeof(char));
        ++*length;
    }
    else {
        *string = (char* ) malloc(2 * sizeof(char));
        *length = 1;
    }

    *string[*length - 1] = character;
    *string[*length] = 0;
}

调试信息

通过gdb调试发现,尽管硬编码分配2个char大小的内存,但初始分配的数组仅能访问1个char,设置第二个位置时触发段错误:

Program received signal SIGSEGV, Segmentation fault.
appendCharacterToString (string=0x7fffffffe0d8,
    character=110 'n', length=0x7fffffffe0d0)
    at hangmanstringutils.c:24
24          *string[*length] = 0;
(gdb)
(gdb) print string
$1 = (char **) 0x7fffffffe0d8
(gdb) print *string
$2 = 0x5555555592a0 "n"
(gdb) print *length
$3 = 1
(gdb) continue
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) break hangmanstringutils.c:12
Breakpoint 1 at 0x555555555612: file hangmanstringutils.c, line 14.
(gdb) run
Starting program: /home/joseph/code/hangman/hangman
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Breakpoint 1, appendCharacterToString (
    string=0x7fffffffe0d8, character=110 'n',
    length=0x7fffffffe0d0) at hangmanstringutils.c:14
14          if (*string != NULL) {
(gdb) print *string
$4 = 0x0
(gdb) print *length
$5 = 0
(gdb) break 19
Breakpoint 2 at 0x55555555565a: file hangmanstringutils.c, line 19.
(gdb) continue
Continuing.

Breakpoint 2, appendCharacterToString (
    string=0x7fffffffe0d8, character=110 'n',
    length=0x7fffffffe0d0) at hangmanstringutils.c:19
19              *string = (char* ) malloc(2 * sizeof(char));
(gdb) print *string
$6 = 0x0
(gdb) print *length
$7 = 0
(gdb) break 21
Breakpoint 3 at 0x555555555677: file hangmanstringutils.c, line 23.
(gdb) continue
Continuing.

Breakpoint 3, appendCharacterToString (
    string=0x7fffffffe0d8, character=110 'n',
    length=0x7fffffffe0d0) at hangmanstringutils.c:23
23          *string[*length - 1] = character;
(gdb) print *string
$8 = 0x5555555592a0 ""
(gdb) print *length
$9 = 1
(gdb) print *string[0]
$10 = 0 '\000'
(gdb) print *string[1]
Cannot access memory at address 0x2c0
(gdb)

解决方案

错误根源:运算符优先级问题

C语言中,数组下标运算符[]的优先级高于解引用运算符*,所以*string[*length]会被解析为*(string[*length])——这相当于把二级指针string当成数组,直接访问它的第*length个元素(一个char*指针),再解引用这个指针,完全偏离了操作字符数组的预期逻辑。

正确写法应为(*string)[index]:先解引用二级指针string得到指向字符数组的一级指针,再用下标访问数组元素。

额外优化:内存分配失败检查

malloc和realloc可能分配失败返回NULL,若不检查会触发未定义行为,建议添加检查逻辑避免内存泄漏或非法访问。

修复后的代码

#include <stdlib.h> // 确保malloc/realloc的头文件被包含

void appendCharacterToString(char** string, char character, unsigned short int * length) {
    if (*string != NULL) {
        // 用临时变量接收realloc返回值,避免分配失败时丢失原指针
        char* temp = realloc(*string, (*length + 2) * sizeof(char));
        if (temp == NULL) {
            return; // 分配失败直接返回
        }
        *string = temp;
        ++*length;
    }
    else {
        *string = malloc(2 * sizeof(char));
        if (*string == NULL) {
            return; // 分配失败直接返回
        }
        *length = 1;
    }

    // 修正运算符优先级,正确访问字符数组
    (*string)[*length - 1] = character;
    (*string)[*length] = '\0';
}

关键修改点说明

  1. 修正运算符优先级:将*string[index]改为(*string)[index],确保操作目标是字符数组而非二级指针数组。
  2. 安全使用realloc:先用临时变量接收返回值,避免分配失败时原指针被覆盖为NULL导致内存泄漏。
  3. 添加分配失败检查:若malloc或realloc返回NULL,直接终止函数,避免后续非法内存访问。
  4. 明确空终止符:用'\0'替代0,更清晰表明是字符串终止符(两者功能等价,但可读性更强)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:47:17