微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试在 C 中重新编码 itoa 时出现段错误 解决方案奖金聊天深入

如何解决尝试在 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 指向的数组可能在适当的位置包含零字节,但您应该设置它以避免未定义的行为。

  • 由于 strft_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 用于存储可执行代码部分(注意 READONLYCODE 标志)
  • .data 用于存储全局变量(注意 DATA 标志并且没有 READONLY 标志)
  • .rodata 用于存储文字数据(注意 READONLYDATA 标志)

我们可以通过以下方式确认 .rodata 部分实际上包含文字字符串 1DF

$ objdump --full-contents --section .rodata

a.out:     file format elf32-littlearm

Contents of section .rodata:
 1060c 01000200 31444600                    ....1DF.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。