EXC_BAD_INSTRUCTION 在函数中使用“strcpy”

问题描述

当我在主函数中使用整个代码时,它运行良好,但现在我想将该函数用于一些我在二维数组中初始化的“字符串”。

函数背后的想法是创建一个全局初始化的结构体的乘积。带有 strcpy 的行给出了错误

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0).

我在 Mac 上使用 Xcode 11.3.1。

你们能帮我解决这个问题吗?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

struct produkt neues_angebot(char *produktname);

struct produkt{
    char name[5];
    int produkt_zahl;
    float produkt_preis;
};

struct produkt neues_angebot(char *produktname){
    time_t t;
    srand((unsigned) time(&t));
    struct produkt Zwischenname = {
        "xxx",(rand() % 49),((rand()% 600)/100)
    };
    strcpy(Zwischenname.name,produktname);
    return Zwischenname;     
}

int main(int argc,const char * argv[]) {
    char teste[]="hello";
    printf("%s\n",neues_angebot(teste).name); 
}

解决方法

C 中的字符串以空字符结尾。字符串 "hello" 使用 6 个字节的存储空间:5 个字符 h e l l o 加上终止的空字符。

现在 strcpy 不进行长度检查,因此 strcpy(Zwischenname.name,produktname) 将尝试将所有 6 个字节复制到数组 Zwischenname.name 中,该数组只有 5 个字节的空间。这会溢出数组并且是未定义的行为 - 您观察到的崩溃是许多可能的结果之一。

,

strcpy 会将 teste 的最后一个字符(空终止符 '\0')复制到目标缓冲区的边界之外,因为它比需要的长度短一个字节,这将导致 Zwischenname.name 不是空终止。

问题是 printf 需要空终止符才能知道字符串在哪里结束才能正常工作,将非空终止字符数组作为参数传递给 printf("%s",argument); 会调用未定义的行为。

请记住,为了将字符数组视为正确的字符串,它需要以空字符结尾,C 中的许多库函数都依赖于这一原则。始终确保它是。