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

为何crypt()函数不接受合法两位nonce?技术排查求助

问题分析与解决方案

你的问题核心是悬挂指针导致的未定义行为,这也是crypt()函数表现异常的根本原因。咱们一步步拆解:

1. 核心问题:concatenateCharacters()返回了无效指针

看你的concatenateCharacters函数:

string concatenateCharacters(char characters[], int arraySize) {
    char terminator[1] = {'\0'};
    char bigEnoughArray[arraySize + 1]; // 局部栈数组
    for (int i = 0; i < arraySize; i++) {
        bigEnoughArray[i] = characters[i];
    }
    return strcat(bigEnoughArray, terminator);
}

bigEnoughArray是函数内部的局部栈内存数组,当函数执行完毕返回时,这个数组所在的栈帧会被销毁,内存会被操作系统回收或后续函数调用覆盖。你返回的是这个数组的地址(strcat返回目标数组的指针),这就成了悬挂指针——指向已经无效的内存区域。

这种情况下,后续使用nonce指针的行为都是未定义的:有时候内存内容还没被覆盖,看似能工作;有时候内存被其他操作(比如第一个crypt()调用)覆盖,就会出现crypt()返回null的情况。

2. 两种输出异常的原因

  • 第一种情况(两个crypt()都调用):第一个crypt("myPassword", "14")的函数调用会使用栈内存,直接覆盖了bigEnoughArray原来的内容,导致nonce指向的内存不再是"14",crypt()拿到无效的salt,返回null。
  • 第二种情况(只调用第二个crypt()):此时bigEnoughArray的内存还没被覆盖,nonce暂时能读到"14",但这只是巧合。crypt()返回的哈希缺少前两位,也是未定义行为的表现——因为内存随时可能被其他操作篡改,结果完全不可靠。

另外还要注意:你定义的nonceAsArray[2]是长度为2的字符数组,没有存储字符串终止符'\0',本质上它不是一个合法的C风格字符串,这也会给后续处理埋下隐患。

3. 修复方案

方案一:用动态内存分配避免悬挂指针

修改concatenateCharacters函数,使用malloc分配堆内存,这样内存不会随函数结束销毁:

string concatenateCharacters(char characters[], int arraySize) {
    // 分配足够的内存存储字符 + 终止符
    char *bigEnoughArray = malloc(arraySize + 1);
    if (bigEnoughArray == NULL) {
        // 内存分配失败,返回NULL或处理错误
        return NULL;
    }
    // 复制字符到新内存
    for (int i = 0; i < arraySize; i++) {
        bigEnoughArray[i] = characters[i];
    }
    // 手动添加字符串终止符
    bigEnoughArray[arraySize] = '\0';
    return bigEnoughArray;
}

注意:使用完nonce后,一定要用free(nonce)释放内存,避免内存泄漏。

方案二:直接在主函数中生成salt字符串

其实没必要单独写拼接函数,直接在主逻辑里处理更简洁:

string hash = "14dJperBYV6zU";
// 分配3字节内存:2个salt字符 + 1个终止符
char *nonce = malloc(3);
if (nonce == NULL) {
    // 处理内存分配失败的情况,比如退出程序
    return 1;
}
// 提取前两位字符
nonce[0] = hash[0];
nonce[1] = hash[1];
// 添加字符串终止符,确保是合法的C字符串
nonce[2] = '\0';

// 调用crypt
printf("first hash: %s\n", crypt("myPassword", "14"));
printf("second hash: %s\n", crypt("myPassword", nonce));

// 释放内存
free(nonce);

4. 后续排查方向

遇到这类时好时坏的异常,优先排查:

  • 指针是否指向已释放的局部内存(悬挂指针)
  • 传递给函数的字符串是否是合法的C风格字符串(必须以'\0'结尾)
  • 内存生命周期问题:局部变量的内存只在函数执行期间有效,不要返回局部变量的地址

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:33:02