矩阵乘法导致不确定的behaviorSanitizer:致命信号错误

发布于 2025-01-23 07:04:56 字数 3962 浏览 1 评论 0原文

试图解决

我想出了这个解决方案:

#include <stdexcept>
#include <iostream>

using std::vector;

static inline long long _determinant(vector<vector<long long>> const& m, vector<std::size_t> const& is, vector<std::size_t> const& js);

long long determinant(vector< vector<long long> > m) {
  for( vector<long long> i : m ) {
    std::cout << "(";
    bool first = true;
    for (long long j : i) {
      if(!first) {
        std::cout << ',';
      }
      std::cout << j;
      first = false;
    }
    std::cout << ")\n";
  }
  std::cout << "\n";

  if (m.empty())
    throw std::domain_error("A determinant cannot be calculated on an empty matrix.");
  if (m.size() != m[0].size())
    throw std::domain_error("A determinant is only defined for a square matrix.");
  if (m.size() == 1)
    return m[0][0];

  std::vector<std::size_t> include_idx(m.size());
  std::generate(include_idx.begin(), include_idx.end(), [] {
    static int i = 0;
    return i++;
  });

  return _determinant(m, include_idx, include_idx);
//   return 0;
}

static inline long long _determinant(vector<vector<long long>> const& m, vector<std::size_t> const& is, vector<std::size_t> const& js) {
  size_t end = is.size();
  if(end == 2)
    return m[is[0]][js[0]] * m[is[1]][js[1]] - m[is[1]][js[0]] * m[is[0]][js[1]];

  long long determinant = 0;
  short sign = 1;
  vector<std::size_t> new_is = is;
  new_is.erase(new_is.begin());
  for( size_t j = 0; j < js.size(); j++) {
      vector<std::size_t> new_js = js;
      new_js.erase(new_js.begin() + j);
      determinant += sign * (m[0][js[j]]) * (_determinant(m, new_is, new_js));;
      sign *= -1;
  }

  return determinant;
};


KATA提供的测试是:

using std::vector;
using testing::Eq;

TEST(libhelloTest, determinantTest) {
  EXPECT_THAT(determinant(vector<std::vector<long long> >{
                  vector<long long>{1}}),
                  Eq(1));
  
  EXPECT_THAT(determinant(vector<std::vector<long long> >{
                  vector<long long>{1, 3},
                  vector<long long>{2, 5},
              }),
              Eq(-1));
  
  EXPECT_THAT(determinant(vector< std::vector<long long> > {
              vector<long long> {2,  5,  3},
              vector<long long> {1, -2, -1},
              vector<long long> {1,  3,  4}
              }),
              Eq(-20));
}

这些在本地运行绝对不错,但是当我将其放入密码器中时,

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000024 (pc 0x000000425ae0 bp 0x7ffc425bf610 sp 0x7ffc425bf550 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
    #0 0x425adf  (/workspace/test+0x425adf)
    #1 0x425d02  (/workspace/test+0x425d02)
    #2 0x4259c5  (/workspace/test+0x4259c5)
    #3 0x428b61  (/workspace/test+0x428b61)
    #4 0x426fbe  (/workspace/test+0x426fbe)
    #5 0x426b3f  (/workspace/test+0x426b3f)
    #6 0x42679b  (/workspace/test+0x42679b)
    #7 0x42b7c5  (/workspace/test+0x42b7c5)
    #8 0x425e6d  (/workspace/test+0x425e6d)
    #9 0x7f8772499bf6  (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #10 0x4046b9  (/workspace/test+0x4046b9)

UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING

我会尝试使用-fsanitize = undefined (我正在使用clang ++ 14.0.1),但这不会复制问题。有谁知道,首先我如何复制此错误,其次,我的代码怎么了?

In trying to solve this kata on codewars (TL;DR implement matrix multiplication).

I've come up with this solution:

#include <stdexcept>
#include <iostream>

using std::vector;

static inline long long _determinant(vector<vector<long long>> const& m, vector<std::size_t> const& is, vector<std::size_t> const& js);

long long determinant(vector< vector<long long> > m) {
  for( vector<long long> i : m ) {
    std::cout << "(";
    bool first = true;
    for (long long j : i) {
      if(!first) {
        std::cout << ',';
      }
      std::cout << j;
      first = false;
    }
    std::cout << ")\n";
  }
  std::cout << "\n";

  if (m.empty())
    throw std::domain_error("A determinant cannot be calculated on an empty matrix.");
  if (m.size() != m[0].size())
    throw std::domain_error("A determinant is only defined for a square matrix.");
  if (m.size() == 1)
    return m[0][0];

  std::vector<std::size_t> include_idx(m.size());
  std::generate(include_idx.begin(), include_idx.end(), [] {
    static int i = 0;
    return i++;
  });

  return _determinant(m, include_idx, include_idx);
//   return 0;
}

static inline long long _determinant(vector<vector<long long>> const& m, vector<std::size_t> const& is, vector<std::size_t> const& js) {
  size_t end = is.size();
  if(end == 2)
    return m[is[0]][js[0]] * m[is[1]][js[1]] - m[is[1]][js[0]] * m[is[0]][js[1]];

  long long determinant = 0;
  short sign = 1;
  vector<std::size_t> new_is = is;
  new_is.erase(new_is.begin());
  for( size_t j = 0; j < js.size(); j++) {
      vector<std::size_t> new_js = js;
      new_js.erase(new_js.begin() + j);
      determinant += sign * (m[0][js[j]]) * (_determinant(m, new_is, new_js));;
      sign *= -1;
  }

  return determinant;
};


The tests provided with the kata are:

using std::vector;
using testing::Eq;

TEST(libhelloTest, determinantTest) {
  EXPECT_THAT(determinant(vector<std::vector<long long> >{
                  vector<long long>{1}}),
                  Eq(1));
  
  EXPECT_THAT(determinant(vector<std::vector<long long> >{
                  vector<long long>{1, 3},
                  vector<long long>{2, 5},
              }),
              Eq(-1));
  
  EXPECT_THAT(determinant(vector< std::vector<long long> > {
              vector<long long> {2,  5,  3},
              vector<long long> {1, -2, -1},
              vector<long long> {1,  3,  4}
              }),
              Eq(-20));
}

These run absolutely fine locally, but when I put it into codewars I get:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000024 (pc 0x000000425ae0 bp 0x7ffc425bf610 sp 0x7ffc425bf550 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
    #0 0x425adf  (/workspace/test+0x425adf)
    #1 0x425d02  (/workspace/test+0x425d02)
    #2 0x4259c5  (/workspace/test+0x4259c5)
    #3 0x428b61  (/workspace/test+0x428b61)
    #4 0x426fbe  (/workspace/test+0x426fbe)
    #5 0x426b3f  (/workspace/test+0x426b3f)
    #6 0x42679b  (/workspace/test+0x42679b)
    #7 0x42b7c5  (/workspace/test+0x42b7c5)
    #8 0x425e6d  (/workspace/test+0x425e6d)
    #9 0x7f8772499bf6  (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #10 0x4046b9  (/workspace/test+0x4046b9)

UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING

I've tried compiling and linking with -fsanitize=undefined (I'm using clang++ 14.0.1) but that doesn't replicate the issue. Does anyone know, firstly how I can replicate this error, and secondly what is up with my code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文