如何解决尝试在 C 中重新编码 itoa 时出现段错误 解决方案奖金聊天深入
新手试图在此处重新编码 itoa
。
我不太确定 itoa 函数是如何工作的,但这是我现在希望我的工作方式:
char *ft_itoa(int nb,char *str)
我希望将 nb
的每个数字转换为一个字符,然后放入 *str
。
这是我的代码(我不允许使用任何函数,但 write
只允许我在这里调试。
char *ft_itoa(int nb,char *str)
{
int i;
int y;
int nbinit;
int neg;
i = 0;
y = 0;
nbinit = nb;
neg = 0;
if(nb < 0)
{
nb = -nb;
neg = 1;
str[i] = '-';
i++;
}
while(nb / 10 > 0)
{
i++;
nb = nb / 10;
}
if(neg == 1)
nb = -nbinit;
else
nb = nbinit;
while(nb / 10 > 0)
{
y = nb % 10;
str[i] = y + '0';
i--;
nb = nb / 10;
}
str[i] = nb + '0';
return (str);
}
程序在尝试执行这一行时会出现段错误:
str[i] = y + '0';
如果我不得不胡乱猜测,我会说这是因为在我的主要内容中
int main(void)
{
char *nbr = "1DF";
int nb = 479;
ft_itoa(nb,nbr);
return (0);
}
*nbr
不是“malloced”。我不确定在声明 char *nbr = "1DF";
时分配是如何工作的。
预先感谢您的帮助!
解决方法
在编译和链接 C 代码时,您的编译器将在生成的可执行文件的不同部分存储各种位和片段。这些被称为“部分”,根据存储在那里的内容,具有不同的保护级别,通常由 CPU 虚拟内存分页机制强制执行。对于文字值(在本例中为 "1DF"
),编译器会将它们存储在标记为只读的部分中。因此:
char *nbr = "1DF";
声明一个指针变量(nbr
,存储在堆栈中),指向存储在只读部分的"1DF"
。
因此,当您尝试修改该字符串的其中一个字符时,CPU 将引发错误;分段错误。
解决方案
您可以将 nbr
声明为指向 char
的固定长度数组的指针(从而使初始内容未定义且未存储在只读部分中),方法是将声明更改为:>
char nbr[4];
声明的数组长度为 4 以容纳尾随零字节以指示字符串的结尾。
奖金聊天
这将“有效”,但您应该考虑以下几点:
-
如前所述,C 中的字符串需要以零字节(字符符号中的
'\0'
)结尾才能被视为有效。根据编译器、优化级别、计算机状态、月相等,nbr
指向的数组可能在适当的位置包含零字节,但您应该设置它以避免未定义的行为。 -
由于
str
的ft_itoa
参数是一个char *
,str
指向的数组的长度在ft_itoa
中是未知的。 C 中的一个常见习惯用法是添加一个参数,它是数组的长度,以便可以安全地使用它,并将返回类型更改为int
以允许指示操作是否成功(例如在nb
的字符串表示无法放入str
指向的数组的情况下)。这将使ft_itoa
的声明类似于int ft_itoa(int nb,char *str,int str_len)
,如果失败则返回0
,如果成功则返回1
。
深入
查看通过编译代码创建的可执行文件,我们有以下说明部分(输出中省略了许多其他部分):
$ objdump --section-headers
a.out: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
...
12 .text 00000324 000102e0 000102e0 000002e0 2**2
CONTENTS,ALLOC,LOAD,READONLY,CODE
...
14 .rodata 00000008 0001060c 0001060c 0000060c 2**2
CONTENTS,DATA
...
21 .data 00000008 0002101c 0002101c 0000101c 2**2
CONTENTS,DATA
...
-
.text
用于存储可执行代码部分(注意READONLY
和CODE
标志) -
.data
用于存储全局变量(注意DATA
标志并且没有READONLY
标志) -
.rodata
用于存储文字数据(注意READONLY
和DATA
标志)
我们可以通过以下方式确认 .rodata
部分实际上包含文字字符串 1DF
:
$ objdump --full-contents --section .rodata
a.out: file format elf32-littlearm
Contents of section .rodata:
1060c 01000200 31444600 ....1DF.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。