【问题标题】:Segmentation Fault before reaching main - C++到达主之前的分段错误 - C++
【发布时间】:2019-10-10 14:23:17
【问题描述】:

我正在编写一个代码来找到一个合适的输入,该输入将为 SHA-1 哈希函数生成特定的输出。

我遇到的问题是我的代码引发了分段错误,但gdb 发现它在输入main() 和执行任何其他代码之前引发以下错误:

Program received signal SIGSEGV, Segmentation fault.
__strncpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:636
636 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.

这是我的代码:

#include <iostream>
#include <cstdlib>
#include <cstring>

#include "sha1.hpp"

int main() {
    char *prefix = "SHA1sha1";
    char *suffix = "chicken and beer";
    std::string hashvalue = "nonzero";
    char *line = "just some dummy string";
    int loop_number = 0;

    while (hashvalue.c_str()[0] != '0' || hashvalue.c_str()[1] != '0') {
        // change prefix
        strncpy(prefix, hashvalue.c_str(), 8);
        // hash the concatenated string of prefix and suffix
        strncpy(line, prefix, 8);
        strncat(line, suffix, strlen(suffix));
        hashvalue = sha1(line);

        loop_number++;
        if (loop_number % 1000 == 0) std::cout << loop_number << "th loop, hash value: " << hashvalue << std::endl;
    }

    std::cout << "Found prefix: " << prefix << " with hash value: " << hashvalue << std::endl;

    return 0;
}

sha1.hpp 不是我实现的,而是取自这里:http://www.zedwood.com/article/cpp-sha1-function

不过,我已将 sha1.h 更改为 sha1.hpp,但这可能不是导致分段错误的原因。

现在我已经尝试使用错误消息以及关键字“main before segmentation fault”来寻找解决此问题的方法,而这篇文章似乎遇到了类似的问题:@987654322 @

但是,我研究了两种建议的解决方案,但找不到适合我的解决方案。

  1. 我认为我的代码在堆栈中没有太多变量。其实我也试过用函数sha1()注释掉以防万一,但还是出现了同样的问题。

  2. 在使用前我已经在我的代码中初始化了所有char*std::string

仅供参考,我正在使用 g++ 编译我的 C++ 代码。

我们将不胜感激任何帮助或推动正确方向。

【问题讨论】:

  • 您的代码不需要使用任何char * 变量。一切都可以std::string,因此更安全。
  • @PaulMcKenzie 是对的,您应该非常谨慎对待使用遗留 C 字符串的 C++ 代码。并不是说您不能,只是如果您只编写 C++ 代码,这很少是一个好主意。
  • @paxdiablo 感谢您的提醒,但下面的答案(我仍在尝试在脑海中处理)说字符串文字无法修改。似乎遗留的 C 字符串更容易编码但不安全......? (我知道它们不安全,因为我在使用它们时遇到了太多错误。我只想知道我在正确的页面上)
  • C 风格的字符串更难处理,而不是更容易!您必须管理它们的生命周期和容量,而 std::string 则不需要。
  • 如果你打开了编译器警告,编译器本身就会指出代码中的错误。

标签: c++ string segmentation-fault undefined-behavior string-literals


【解决方案1】:

您正在修改不可变内容。

// change prefix
strncpy(prefix, hashvalue.c_str(), 8);
// hash the concatenated string of prefix and suffix
strncpy(line, prefix, 8);
strncat(line, suffix, strlen(suffix)); 

尝试如下更改声明。

char prefix[100] = "SHA1sha1";
char suffix[200] = "chicken and beer";
char line[200] = "just some dummy string

还有,我猜

while (hashvalue.c_str()[0] != '0' || hashvalue.c_str()[1] != '0') {

应该是

while (hashvalue.c_str()[0] != '0' && hashvalue.c_str()[1] != '0') {

更新:

德摩根定律指出,

not (A and B) = not A or not B

再次,个人可以选择使用他们想要的任何形式

【讨论】:

  • 感谢您的回答!但是为什么人们认为while循环条件写错了呢?当哈希值的前两个字母为 00 时,我试图让它停止。
  • 我实际上编辑了最后一条评论,你能重新检查一下吗?谢谢。
  • 根据德摩根定律,它是not (A and B) = not A or not B。同样,使用他们想要的任何形式都是个人的选择。 @정진하
【解决方案2】:

字符串文字在 C++ 中具有常量字符数组的类型,任何修改字符串文字的尝试都会导致未定义的行为。您正在尝试至少在此语句中修改字符串文字:

strncpy(prefix, hashvalue.c_str(), 8);

您应该使用字符数组或std::string 类型的对象,而不是字符串字面量。

注意这一点;例如这个if 声明

while (hashvalue.c_str()[0] != '0' || hashvalue.c_str()[1] != '0') {

可以写得更简单:

while (hashvalue[0] != '0' || hashvalue[1] != '0') {

虽然看起来这个条件没有意义。也许你的意思是以下

while ( hashvalue.size() > 1 ) {

您还需要包含标题&lt;string&gt;

#include <string>

【讨论】:

  • 对于情况奇怪的部分,情况并非如此。但是谢谢你的回答!真的很有帮助。
  • 您声明修改字符串文字是 UB。然而,我认为这个程序有 UB 它甚至不必这样做。 prefix 和其他不是 const 的人本身就是 UB,如果我没记错的话。
  • @Chipster 声明指向不带限定符 const 的字符串文字的指针本身并不是未定义的行为,尽管标准不允许这样做。编译器可以允许这样做以实现向后兼容性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-31
  • 2012-07-08
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多