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

在C中调用NASM数据段db字符串触发段错误

问题根源与解决方案

问题分析

段错误的核心是C代码与汇编代码的类型不匹配:

  • 汇编中foo: db "bar", 0定义的是直接存储在.data段的字符串,foo是该字符串的起始地址(本身就是字符数组的首地址)。
  • 但C代码里声明extern char *foo,表示foo是一个指向字符的指针变量,而非字符数组/字符串本身。

程序运行时,puts(foo)会把foo的值当作指针访问内存。而foo对应的字符串内容是"bar"(ASCII码为0x62 0x61 0x72 0x00),小端模式下系统会把低64位0x00726162当作指针地址,这个地址属于非法内存区域,直接触发段错误。gdb输出的$1 = 0x726162 <error: Cannot access memory at address 0x726162>也验证了这一点——程序把字符串内容当成了指针地址。

两种修复方案

方案1:修改C代码的声明,匹配汇编实际类型

将C里的extern char *foo改为extern char foo[](或extern const char foo[],字符串建议放只读段,更安全):

#include <stdio.h>

extern char foo[]; // 声明为字符数组,而非指针

int main() {
    puts(foo);
}

方案2:修改汇编代码,定义指针变量指向字符串

如果必须在C里保留char *foo的指针声明,汇编中需要定义一个指针变量指向字符串地址:

global foo

section .rodata ; 字符串建议放只读段,避免意外修改
str_bar: db "bar", 0

section .data
foo: dq str_bar ; 64位系统下定义8字节指针,指向str_bar的地址

额外建议

  • 字符串常量推荐放在.rodata段(汇编)或用const修饰(C),提升安全性。
  • 编译时添加-Wall参数,比如gcc -Wall main.c foo.o,会触发类型不匹配的警告,帮助快速定位问题:
    warning: initialization of ‘char *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:10:58