简体   繁体   English

c分段错误(核心转储)错误

[英]c segmentation fault (core dumped) error

I tried to compile this program but I got a message saying "segmentation fault (core dumped)", by the compiler. 我尝试编译该程序,但编译器收到一条消息,提示“分段错误(内核已转储)”。 Could anyone please tell me what is wrong? 谁能告诉我出什么事了吗?

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

#define power(x,y) (int)pow((double)x,(double)y)

/*-------------------setBits-------------------*/
/* A function to set the i (and following) bit(s) to be 'number'. The function takes  'number' and adds the matching powers of 2 to 'destination'. */
void setBits(int number, int i, int *destination) {
      for( ; number!=0 ; number/=2 , i++)
        (*destination) += (number % 2) * (power(2, i));
}

/*-------------------getDigit-------------------*/
/* A function that returns a string of 'number' converted to base 32. */
char getDigit(int number) {
    char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
    return digits[number];
}
/*-------------------get32-------------------*/
/* A function that returns a string of 'number' converted to base 32. */
char *get32(int number) {
    char *result = "";
    if (number/32 == 0)
        result[0] = getDigit(number);
    else strcat(result,get32(number/32));
    return result;
}

/*-------------------main-------------------*/
int main(){
    int test = 0;
    setBits(23, 5, &test);
    printf("%s", get32(test));
    return 0;
}

Also if anybody has tips to get the code better I'd love to get advices (: Thanks. 另外,如果有人有改进代码的技巧,我也很乐意获得建议(:谢谢。

Handling strings in C is tricky; 用C处理字符串很棘手。 you cannot split and concatenate them easily as you can do in scripting languages. 您无法像使用脚本语言一样轻松地拆分和连接它们。 Strings are arrays of chars whose storage must be handled by the user. 字符串是字符数组,其存储必须由用户处理。 That's also the cause of your segmentation violation: You try to modify read-only memory. 这也是造成分段违规的原因:您尝试修改只读内存。

Other answers suggest using malloc . 其他答案建议使用malloc This is a viable way to get memory to hold the strigs, but it has a drawback: The memory has to be freed. 这是一种获取内存以容纳strig的可行方法,但它有一个缺点:必须释放内存。 That means that you can't use the return value of get32 directly in printf , because you must keep the handle to the allocated string somewhere. 这意味着您不能直接在printf使用get32的返回值,因为您必须将分配的字符串的句柄保留在某个地方。

This also means that your recursive solution isn't suited to C, becaouse you'd have to free all intermediate strings. 这也意味着您的递归解决方案不适用于C,因为您必须free所有中间字符串。

In your case, the string you need is short. 在您的情况下,您需要的字符串很短。 You want to print a 32-bit number in base 32. This number can have at most 7 digits, so you need eight bytes. 您希望以32为基数打印一个32位数字。该数字最多可以有7位数字,因此需要八个字节。 (The eighth byte is for storing the terminating null character.) (第八个字节用于存储终止空字符。)

Another useful method that doesn't use allocation is to pass in a buffer of a certain length and have the function fill it. 另一种不使用分配的有用方法是传入一定长度的缓冲区并让函数填充它。 The function must receive the array and its length as parameters: 该函数必须接收数组及其长度作为参数:

char *get32(char buf[], int len, int number)
{
    const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
    int n = len;

    buf[--n] = '\0';
    memset(buf, '0', n);

    while (number) {
        buf[--n] = digits[number % 32];
        number /= 32;
    }

    return &buf[n];
}

This function writes a number with len - 1 digits, all zero initially, and then returns a pointer to the first non-zero digit, so that you can print it. 此函数写入len - 1位数字,最初全为零,然后返回指向第一个非零数字的指针,以便可以打印它。 The char buffer is provided by the calling function: char缓冲区由调用函数提供:

int main()
{
    int test = 0;
    char buf[8];

    setBits(23, 5, &test);
    puts(get32(buf, sizeof(buf), test));

    return 0;
}

Of course, if you want to print two numbers in the same printf , you must use different buffers, or the buffer will be overwritten. 当然,如果要在同一printf打印两个数字,则必须使用不同的缓冲区,否则缓冲区将被覆盖。

You need to allocate memory for result. 您需要为结果分配内存。 Add

#include <stdlib.h>

and change the declaration of result to 并将结果声明更改为

char *result = calloc( BUFSIZE, sizeof(char));

where BUFSIZE is the maximum length result can get plus one for the terminating '\\0'. 其中BUFSIZE是最大长度结果,可以将结尾的'\\ 0'加一。 calloc() fills the allocated memory with zeroes so your result string will be terminated correctly. calloc()用零填充分配的内存,因此您的结果字符串将正确终止。

To avoid a memory leak, you should then also free the buffer after each call to get32(): 为了避免内存泄漏,您还应该在每次调用get32()之后释放缓冲区:

char *result = get32(...)
printf("%s", result);
free(result);

in main() and likewise after the call in get32() itself. 在main()中,同样在get32()本身调用之后。

Your error lies here: 您的错误在这里:

char *result = "";
strcat(result,get32(number/32));

man strcat will confirm you that the first expected argument is the destination where the resulting string is written. man strcat将确认您第一个预期参数是将结果字符串写入的目标位置。 Since you gave result as the destination, strcat() will try to write to result . 由于您将result作为目标,因此strcat()将尝试写入result Unfortunately, this pointer points to a special destination of the binary program where its literal strings (here: "" ) are registered; 不幸的是,该指针指向二进制程序的特殊目标,在该目标中注册了其文字字符串(此处为"" )。 this section is read-only . 本部分是只读的

strcat() tries to write to a read-only section => BOOM => SIGSEGV. strcat()尝试写入只读节=> BOOM => SIGSEGV。

You should allocate ( malloc() ) memory for result and use strncat() : 您应该为result分配( malloc() )内存,并使用strncat()

char* const result = malloc(SOME_SIZE*sizeof(char));
result[0] = '\0';
strncat(result, get32(number/32), SOME_SIZE);

And finally, don't forget to free(result) ;). 最后,不要忘记free(result) ;)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM