我最近在 Leetcode Biweekly Competition 78 中做第一个问题,我收到了一个我无法理解的意外 runtime error ,特别是因为我之前写过类似的代码,它运行良好。我对编程和这些比赛很陌生,请告诉我这个 Runtime Error 是什么意思以及如何更改我的代码来修复它。
class Solution {
public:
int divisorSubstrings(int num, int k) {
string b=to_string(num);
string a="";
int x;
int ans=0;
for(int i=0;i<=b.size()-k;++i){
for(int j=i;i<i+k;++j){
a+=b[j];
}
x=stoi(a);
if(num%x==0){
++ans;
}
}
return ans;
}
};
和错误:
=================================================================
==33==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffca3ed0900 at pc 0x000000343d81 bp 0x7ffca3ed0890 sp 0x7ffca3ed0888
READ of size 1 at 0x7ffca3ed0900 thread T0
#2 0x7fe89b85d0b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Address 0x7ffca3ed0900 is located in stack of thread T0 at offset 96 in frame
This frame has 4 object(s):
[32, 40) '__endptr.i'
[64, 96) 'b' <== Memory access at offset 96 overflows this variable
[128, 160) 'a'
[192, 193) 'ref.tmp'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x1000147d20d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d20e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d20f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2110: 00 00 00 00 f1 f1 f1 f1 f8 f2 f2 f2 00 00 00 00
=>0x1000147d2120:[f2]f2 f2 f2 00 00 00 00 f2 f2 f2 f2 f8 f3 f3 f3
0x1000147d2130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2140: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x1000147d2150: 01 f2 04 f2 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000147d2170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==33==ABORTING
如果您需要这个问题,请访问 https://leetcode.com/contest/biweekly-contest-78/problems/find-the-k-beauty-of-a-number/
谢谢
回答1
你的问题是这行代码:
for(int j=i;i<i+k;++j){
你有两个习惯应该改掉。首先,您不使用空格。这使得这一行中的错误更难阅读。其次,您使用非常短的变量名。这也使这一行中的错误更难阅读。
那个for循环永远循环。问题是中心子句:
i < i + k
注意当我添加空格时它有多明显?随着年龄的增长和眼睛的老化,这个问题会变得更糟。代码开始像一堵无法阅读的文本墙。像我这样的老屁将无法阅读您的代码。
所以,请添加一点空白。我会这样写那行:
for (int j = i; j < i + k; ++j) {
是的,它需要更多的水平空间。空间很便宜。虫子很贵。
请注意,我仍然认为此代码将超出 b 的大小范围,因此您可能仍然会遇到问题。
回答2
这是从您的代码段修改的公认解决方案。查看所做的更改。
class Solution {
public:
int divisorSubstrings(int num, int k) {
string b = to_string(num);
int ans = 0;
for(int i = 0; i <= b.size() - k; i++) { // the error causing crash
string a = ""; // keep declation close to it's usage, compiler will optimize declaration
for(int j = i; j < i + k; j++) a += b[j];
int x = stoi(a);
if (!x) continue; // you might not want to devide by 0
if( num % x == 0 ) ans++;
}
return ans;
}
};