Reputation: 343
I am trying to implement a program to identify whether a number is a palindrome or not. I had earlier implemented the program using vector and the program worked fine. Now, I want to implement it using integer array. The code works fine on my setup, but gave a Runtime error on Leetcode.
Here is the code:-
main.cpp
#include<iostream>
class Solution
{
int*arr;
size_t size;
//function that puts the digits of the number in an array
void helper(int n,int*digits)
{
static int idx=-1;
idx++;
if((n/10)==0)
{
digits[idx]=n;
return;
}
else
{
digits[idx]=(n%10); //line that gave error
helper(n/10,digits);
}
}
public:
Solution()
:arr(NULL),size(0) {}
bool isPalindrome(int x)
{
int n=x;
if(x<0) return false;
while(x != 0)
{
size++;
x/=10;
}
arr=new int[size];
helper(n,arr);
for(size_t i=0;i<size;i++)
if(arr[i] != arr[size-1-i])
return false;
return true;
}
~Solution()
{
delete[] arr;
}
};
int main(int argc,char**argv)
{
int n;
Solution sol;
printf("Enter a number: ");
scanf("%d",&n);
printf("Is the number %d a palindrome? %d\n",n,sol.isPalindrome(n));
printf("Press any key to continue...\n");
getchar();
getchar();
return EXIT_SUCCESS;
}
Edited:
Full error message:-
==23==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x50200000003c at pc 0x562a5f4a30af bp 0x7ffdc7e88500 sp 0x7ffdc7e884f8
WRITE of size 4 at 0x50200000003c thread T0
#0 0x562a5f4a30ae in Solution::helper(int, int*) solution.cpp:17:24
#1 0x562a5f4a2df0 in Solution::isPalindrome(int) solution.cpp:17:9
#2 0x562a5f4a2819 in __helper__ solution.cpp:17:29
#3 0x562a5f4a2819 in main solution.cpp:17:41
#4 0x7fa2bc460d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
#5 0x7fa2bc460e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
#6 0x562a5f3d1954 in _start (solution+0xab954)
0x50200000003c is located 0 bytes after 12-byte region [0x502000000030,0x50200000003c)
allocated by thread T0 here:
#0 0x562a5f4a02fd in operator new[](unsigned long) /root/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:98:3
#1 0x562a5f4a2dc2 in Solution::isPalindrome(int) solution.cpp:17:13
#2 0x562a5f4a2819 in __helper__ solution.cpp:17:29
#3 0x562a5f4a2819 in main solution.cpp:17:41
#4 0x7fa2bc460d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
SUMMARY: AddressSanitizer: heap-buffer-overflow solution.cpp:17:24 in Solution::helper(int, int*)
Shadow bytes around the buggy address:
0x501ffffffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x502000000000: fa fa fd fd fa fa 00[04]fa fa fa fa fa fa fa fa
0x502000000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==23==ABORTING
Upvotes: 0
Views: 81
Reputation: 123322
This
static int idx=-1;
is most certainly wrong and will lead to accessing the array out of bounds when Solution
is used for the second test case. Maybe there are other bugs, but this is the most obvious and would explain why your code that uses a single test case looks fine while it crashes online.
To get the digits of a user supplied number is much simpler when you can assume the input is valid and non-negative:
std::string digits;
std::cin >> digits;
I had earlier implemented the program using vector and the program worked fine. Now, I want to implement it using integer array.
I suppose you want to do this for learning purpose which is of course ok. However, learning how to manually manage a dynamic array and mix that with your buisness logic is what you have to learn to avoid, there is no right way to do it. If you do not use std::vector
you can write your custom class that encapsulates the dynamically allocated array and use that. new
and delete
do not belong in a class that checks if a string is a paliondrome. Managing a dynamically allocated array is enough for a class to do. Learn how to keep things simple, not how to make them complicated.
Upvotes: 2