简体   繁体   English

将字符串元素复制到另一个字符串时出现分段错误

[英]Segmentation fault on copying string elements to another string

Why am I getting segmentation fault? 为什么会出现细分错误? I have listed my code below. 我在下面列出了我的代码。

Please tell if anyone knows what is my fault here and how do I correct it? 请告诉是否有人知道我的错在哪里,我该如何纠正?

What I am trying to do here 我在这里想做什么

I am trying to take numbers as input and for them I have to output a string of characters. 我试图将数字作为输入,而对于它们,我必须输出一个字符串。

Problem 问题

link to the problem is here. 问题的链接在这里。

The code of my proposed solution 我建议的解决方案的代码

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

int main() {

    long long int n, k;
    char manku[] = { 'm', 'a', 'n', 'k', 'u' };
    char l[10000000];
    int t, i = 0, j, p;
    scanf("%d", &t);

    while (t > 0)
    {
        scanf("%lld", &n);

        while (n > 0)
        {
            j = n % 5;
            if (j == 0)
                l[i] = manku[4];
            else
                l[i] = manku[j - 1];

            n = n / 5;
            i++;
        }

        p = strlen(l);

        for (i = 0; i < p; i++)
            l[i] = l[p - 1 - i];

        for (i = 0; i < p; i++)
            printf("%c", l[i]);

        t--;
    }

    return 0;
}
char l[10000000];

This huge array is overflowing your stack memory. 这个巨大的数组溢出了您的堆栈内存。
The stack memory segment is an area of memory allotted for automatic variables and its size is fairly small. 堆栈内存段是分配给自动变量的内存区域,其大小很小。 It is not a good idea to have such a huge array in stack. 拥有如此庞大的数组并不是一个好主意。 Try to allocate it dynamically, like this: 尝试动态分配它,如下所示:

char *l;
l = malloc(10000000);  //note: size of char is 1

With this, the memory allocated to l in heap segment. 这样,在堆段中分配给l的内存。 Make sure to free it once you done with it. 完成后,请确保将其free

Alternatively, you can make l a global variable or a static local variable so that it will go in Data Segment . 或者,您可以将l全局变量或静态局部变量,以便将其放入Data Segment中

Firstly, initialize the variable i after scanning n . 首先,在扫描n之后初始化变量i

while(t>0) {
    scanf("%lld",&n);
    i = 0; /* initialize i every time here */

    while(n>0) {
       /* some code */
    }
}

Also instead of creating stack created array like char l[10000000]; 同样,与其创建堆栈,也不像char l[10000000];这样创建数组char l[10000000]; create the dynamic array once before while loop and free the dynamically allocated memory once done. while循环之前创建一次动态数组while并在完成后free动态分配的内存。 for eg 例如

char *l = malloc(SIZE); /* define the SIZE */
...
...
free(l);

You are getting a segmentation fault when you start running your binary because you are running out of stack memory due to the big size of your array char l[10000000] (you can check the size of your stack by running 当您开始运行二进制文件时,您会遇到分段错误,因为由于数组char l[10000000]的大容量而导致堆栈内存不足(您可以通过运行以下命令检查堆栈的大小)

$ ulimit -s

in your shell). 在您的外壳中)。

There are at least two solutions to this: 至少有两种解决方案:

  1. Increase the size of your stack. 增加堆栈的大小。 You can do this by running, eg, 您可以通过运行例如

     $ ulimit -s unlimited 

    in your shell before running the binary. 在运行二进制文件之前先在您的外壳中插入。

  2. Use malloc to allocate the l array, so that it is allocated in the heap rather than in the stack. 使用malloc分配l数组,以便将其分配在堆中而不是在堆栈中。

Short Answer: The segmentation fault is caused by char l[10000000]; 简短的回答:分段错误是由char l[10000000];引起的char l[10000000]; . Decalring char l[26]; 去除char l[26]; is sufficient. 足够了。

Details 细节

As others said the allocation char l[10000000]; 正如其他人所说,分配char l[10000000]; causes the segmentation fault. 导致分段错误。 You do not need this much memory. 您不需要这么多的内存。 The question stated that the maximum value for n is 10^18. 问题表明, n的最大值为10 ^ 18。 Thus the maximum length of a word would be 26 characters. 因此,一个单词的最大长度为26个字符。 Thus, char l[26]; 因此, char l[26]; is sufficient. 足够了。

Explanation: It is given that you have 10^18 options to arrange k characters. 说明:假定您有10 ^ 18个选项来排列k字符。 Each charater has 5 options and thus the number of options to arrange these characters is 5^k . 每个字符都有5个选项,因此排列这些字符的选项数为5^k Now, you just have to find k : 现在,您只需要找到k

5^k = 10^18  ==>  k = log_5(10^18) ~= 25.75218 < 26 

Implementation 实作

Regarding the implementation, you have few wrong things going on. 关于实现,您很少出错。

  • You do not set i = 0; 您未设置i = 0; after each input scan. 每次输入扫描后。
  • Your can not use strlen without the terminating null-character. 没有终止的空字符您不能使用strlen You should add l[i] = '\\0'; 您应该添加l[i] = '\\0'; above p = strlen(l); p = strlen(l);之上p = strlen(l); .
  • Your second for loop, the one that should revert the string, is not working properly. 您的第二个for循环(应还原字符串的循环)无法正常工作。 Each step changes the string and the steps after it use the changed string (instead of working with the original one). 每一步都会更改字符串,并在使用更改后的字符串后更改步骤(而不是使用原始字符串)。

Regarding the algorithm, it does not work properly as well. 关于算法,它也无法正常工作。 I can give you a hint: this problem is similar to counting in base-5 . 我可以给你一个提示:这个问题类似于在base-5中计数。

Comments 评论

The things above are just few things that I have noticed. 以上只是我注意到的几件事。 I think you should consider rewriting the code since it may still contaion small flaws. 我认为您应该考虑重写代码,因为它可能仍然会污染一些小缺陷。

Another tip: for printing strings (character arrays in c) you can use 另一个技巧:对于打印字符串(c中的字符数组),可以使用

printf("%s", str);

Assuming that str is an array of character that ends with the terminating null-character. 假设str是一个以终止的空字符结尾的字符数组。 Some more information here . 一些更多的信息在这里

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

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