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

时间:2016-03-10 09:34:16

标签: c linux ubuntu segmentation-fault ubuntu-12.04

我尝试编译这个程序,但编译器收到一条消息“分段错误(核心转储)”。谁能告诉我有什么问题?

#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;
}

如果有人提示更好地获取代码我也很乐意得到建议(: 感谢。

3 个答案:

答案 0 :(得分:3)

在C中处理字符串很棘手;你不能像在脚本语言中那样轻松地拆分和连接它们。字符串是字符数组,其存储必须由用户处理。这也是您违反分段的原因:您尝试修改只读内存。

其他答案建议使用malloc。这是获取内存以保存strigs的可行方法,但它有一个缺点:必须释放内存。这意味着您不能直接在get32中使用printf的返回值,因为您必须将句柄保留在分配的字符串中。

这也意味着你的递归解决方案不适合C,因为你必须free所有中间字符串。

在您的情况下,您需要的字符串很短。您希望在基数32中打印32位数。此数字最多可包含7位数,因此您需要8个字节。 (第八个字节用于存储终止空字符。)

另一个不使用分配的有用方法是传入一定长度的缓冲区并让函数填充它。该函数必须接收数组及其长度作为参数:

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];
}

此函数写入一个数字为len - 1的数字,最初为零,然后返回指向第一个非零数字的指针,以便您可以打印它。 char缓冲区由调用函数提供:

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

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

    return 0;
}

当然,如果要在同一printf中打印两个数字,则必须使用不同的缓冲区,否则缓冲区将被覆盖。

答案 1 :(得分:1)

您需要为结果分配内存。添加

#include <stdlib.h>

并将结果声明更改为

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

其中BUFSIZE是终止&#39; \ 0&#39;的最大长度结果加一。 calloc()用零填充分配的内存,以便正确终止结果字符串。

为了避免内存泄漏,您应该在每次调用get32()后释放缓冲区:

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

在main()中,同样在get32()本身调用之后。

答案 2 :(得分:0)

你的错误在于:

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

man strcat将确认您的第一个预期参数是 destination ,其中写入了结果字符串。由于您已将result作为目标,strcat()将尝试写入result。不幸的是,这个指针指向二进制程序的特殊目标,其中文字字符串(此处为:"")已注册;此部分是只读

strcat()尝试写入只读部分=&gt; BOOM =&gt; SIGSEGV。

您应该为malloc()分配(result)内存并使用strncat()

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

最后,不要忘记free(result);)。