crash while replacing string - c++

I've written this code to replace string in substring (even if previous string was smaller than new). My problem is: crash while RtlMoveMemory()
Here is my function:
char* strreplace(char* s, const char* s1, const char* s2)
{
char* p = strstr(s, s1);
if (p != NULL) {
size_t len1 = lstrlenA(s1);
size_t len2 = lstrlenA(s2);
if (len1 != len2)
{
RtlMoveMemory(p + len2, p + len1, lstrlenA(p + len1) + 1);
}
RtlCopyMemory(p, s2, len2);
}
return s;
}

RtlMoveMemory does not allocate any memory, so your program will crash if the new string is longer than the old string.
Is there any good reason that you are trying to do this with RtlMoveMmeory and RtlCopyMemory instead of standard functions?

Related

longest palindromic substring. Error: AddressSanitizer, heap overflow

#include<string>
#include<cstring>
class Solution {
void shift_left(char* c, const short unsigned int bits) {
const unsigned short int size = sizeof(c);
memmove(c, c+bits, size - bits);
memset(c+size-bits, 0, bits);
}
public:
string longestPalindrome(string s) {
char* output = new char[s.length()];
output[0] = s[0];
string res = "";
char* n = output;
auto e = s.begin() + 1;
while(e != s.end()) {
char letter = *e;
char* c = n;
(*++n) = letter;
if((letter != *c) && (c == &output[0] || letter != (*--c)) ) {
++e;
continue;
}
while((++e) != s.end() && c != &output[0]) {
if((letter = *e) != (*--c)) {
const unsigned short int bits = c - output + 1;
shift_left(output, bits);
n -= bits;
break;
}
(*++n) = letter;
}
string temp(output);
res = temp.length() > res.length()? temp : res;
shift_left(output, 1);
--n;
}
return res;
}
};
input string longestPalindrome("babad");
the program works fine and prints out "bab" as the longest palindrome but there's a heap overflow somewhere. Error like this appears:
Read of size 6 at ...memory address... thread T0
"babad" is size 5 and after going over this for an hour. I don't see the point where the iteration ever exceeds 5
There is 3 pointers here that iterate.
e as the element of string s.
n which is the pointer to the next char of output.
and c which is a copy of n and decrements until it reaches the address of &output[0].
maybe it's something with the memmove or memset since I've never used it before.
I'm completely lost
TL;DR : mixture of char* and std::string are not really good idea if you don't understand how exactly it works.
If you want to length of string you cant do this const unsigned short int size = sizeof(c); (sizeof will return size of pointer (which is commonly 4 on 32-bit machine and 8 on 64-bit machine). You must do this instead: const size_t size = strlen(c);
Address sanitizers is right that you (indirectly) are trying to get an memory which not belongs to you.
How does constructor of string from char* works?
Answer: char* is considered as c-style string, which means that it must be null '\0' terminated.
More details: constructor of string from char* calls strlen-like function which looks like about this:
https://en.cppreference.com/w/cpp/string/byte/strlen
int strlen(char *begin){
int k = 0;
while (*begin != '\0'){
++k;
++begin;
}
return k;
}
If c-style char* string does not contain '\0' it cause accessing memory which doesn't belongs to you.
How to fix?
Answer (two options):
not use mixture of char* and std::string
char* output = new char[s.length()]; replace with char* output = new char[s.length() + 1]; memset(output, 0, s.length() + 1);
Also you must delete all memory which you newed. So add delete[] output; before return res;

How to fix 'Heap has been corrupted 'error in c++?

When I run the program, I get exception "heap has been corrupted" after completion of the function
I have read that this exception may cause if you are using memory that has been freed, or when you are writing to index which is out of array index. But none of the cases applies here. I have read other answers of some problems but it didn't help much.
`char fileNametoExport[26]="d:\\FOlder1\\part1.ipt";
char WorkingFolderName[260] ="d:\\folder";
int start = rFind(fileNametoExport, '\\');
int finish = rFind(fileNametoExport, '.');
if (start == -1)
start = 0;
char partname[260];
strcpy(partname,substr(fileNametoExport, start, finish));
::AfxMessageBox((LPCTSTR)partname);
char xtfile[260];
char xmltxtfile[260];
strcpy(xtfile, strcat(WorkingFolderName, partname));
strcat(xtfile, "__Default.x_t");
strcpy(xmltxtfile, WorkingFolderName);
strcat(xmltxtfile,"_XT_SE_INV_Default_SOLID_0_Solid1_xt.xmt_txt");`
function rfind() to find occurence of char in char array-
int rFind(char* s, char c)
{
int sz = 0;
char *tmp = s;
while (*tmp != '\0')
{
sz++;
tmp++;
}
for (int i = sz - 1; i >= 0; i--)
{
if (*(s + i) == c)
return i;
}
return -1;
}
function substr() to get substring from position x to y (y exclusive)
char* substr(char* s, const int b, const int f)
{
char *str = new char[f - b];
int t = 0;
for (int i = b; i != f; i++)
{
str[t] = s[i];
t++;
}
str[t] = '\0';
return str;
}
P.S- While giving input I ensure that fileNametoExport always contains '.' and '\'.
Your program do not check lengths of input strings. You can receive a string longer than your buffer and program will fail.
If your program get fileNametoExport = "d:\\somefolder\\somefilewithoutdot" , finish will be -1 and program fail at strcpy(partname,substr(fileNametoExport, start, finish)); .
Program writes after buffer in char* substr(char* s, const int b, const int f) at line
str[t] = '\0';
because t at this point equal f-b , size of str buffer.
Function _ASSERTE( _CrtCheckMemory( ) ); from <crtdbg.h> very useful when searching for bugs like this. Put it around suspicious code and it fails after your bug. It works only in debug.

Swap 2 char of a C++ array

I have a problem with memory access. When i = 0, Visual Studio throws an exception with reference to a line as labelled in the following code.
Can't access at 0x00AD8B3B and 0x00AD8B3B equals scr+np-i
How can I fix the for-loop body so as to fix this issue?
int o_strrev(char* scr)
{
int np = strlen(scr) - 1;
char tmp;
if (!scr) return -1;
if (!*scr) return -1;
for (int i = 0; i < np / 2; i++)
{
tmp = scr[np-i];
scr[np-i] = scr[i]; # this line
scr[i] = tmp;
}
return 0;
}
As pointed out by #Revolver_Ocelot, you are probably passing a const char* from a string literal. Since these are, by definition, constant, you can't modify them in the way you're trying to. You need some way to convert const char* into a non constant char*. Something along these lines will work for you:
string str = "string";
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
I've compiled your code in g++ using non constant char* and it works fine. Just remember to deallocate your char* when you're done with it. We don't want memory leaks ;)
I see you are trying to reverse a string.
Might I suggest a simpler way
void reverse(char *string_var)
{
int length, c;
char *begin, *end, temp;
length = strlen(string_var);
begin = string_var;
end = string_var;
for (c = 0; c < length - 1; c++)
end++;
for (c = 0; c < length/2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
Make sure you pass character array of the form
char word[64]
Or maybe by recursion
void reverse(char *x, int begin, int end)
{
char c;
if (begin >= end)
return;
c = *(x+begin);
*(x+begin) = *(x+end);
*(x+end) = c;
reverse(x, ++begin, --end);
}
You're most likely calling o_strrev with a string literal, some thing like:
o_strrev("This ain't gonna work!");
This will compile with most compilers and at most generate a warning. Try cranking up your warning level.
Instead, you want to make a dynamic copy of your string on the heap and work with a char* pointer to that, something like:
string str = "This is gonna work!!"
size_t len = str.size();
char* my_string = new char[len + 1];
strncpy(my_string, str.data(), len)
my_string[len] = '\0';
o_strrev(my_string);
// ...
delete[] my_string;

C-style String Homework

My C++ class is going over C-style strings and working with pointers. I'm to write a function that has three parameters: a char * s1, a const char * s2, and a size_t max, which represents that maximum size of the s1 buffer. I am to append the characters in s2 to the end of s1. The directions advise me to make sure there is only one '\0' at the end of the combined characters and I am not to go beyond the end of the buffer I'm asked to copy to. The function will return a pointer to the first character in s1.
I cannot use any functions in the standard library. What I can use are pointers, pointer arithmetic or array notation.
I've started, but not sure where to go.
const char * myFunction (char * s1, const char * s2, size_t max)
{
char * begin = s1;
while (*s1) s1++;
while ((s1 < begin + max - 1) && (*s2 != '\0')) {
*s1++ = *s2++;
}
return s1;
}
Not sure what to do after reaching the end of s1. How would I put s2 to the end of s1?
I cannot use any functions in the standard library.
The only required one would be strlen(), I think. Roll your own:
#define min(a,b) ((a) < (b)) ? (a) : (b)
size_t str_length(const char* s)
{
size_t len = 0;
for( ; *s; ++s, ++len);
return len;
}
const char * append (char * s1, const char * s2, size_t max)
{
if(!s1 || !s2) //If either of strings is NULL, nothing to be done
return s1;
size_t s1_length = str_length(s1);
if(s1_length < max - 1) //If there is a room in s1...
{
size_t s2_length = str_length(s2); //Get length of s2
size_t append_size = min(s2_length, max - s1_length - 1); //Make sure we won't copy more than buffer can hold
if(append_size > 0)
{
memcpy(s1 + s1_length, s2, append_size); //This will overwrite null terminator in 's1'
s1[s1_length + append_size] = 0;
}
}
return s1;
}
Test:
int main(void)
{
char dest[64] = "This is a test";
append(dest, " of strings appending", 64);
printf("%s (length: %d)\n", dest, str_length(dest));
append(dest, " of appending too long string, that will probably not fit inside destination buffer", 64);
printf("%s (length: %d)\n", dest, str_length(dest));
return 0;
}
Output:
This is a test of strings appending (length: 35)
This is a test of strings appending of appending too long strin (length: 63)
Here is working sample.

why my simple reverse char* does not working?

i wrote this code in two ways
trying to run in visual studio 2012 - i open the project as simple console application and i get access valuation exception.
code 1
void revReq(char* str)
{
if(*(str+1) != '\0')
revReq(str+1);
putchar(*str);
}
Code 2
void rev(char* str)
{
char* retVal = new char[strlen(str)]+1;
char* ptr = str + strlen(str)-1;
int i = 0;
while(ptr != str)
{
retVal[i++]=*ptr;
*ptr = '\0';
ptr--;
}
}
the inpus is
char* n = "abcdef";
revReq(n);
the exception
Unhandled exception at 0x00B11E7C in Ex003.exe: 0xC0000005: Access violation reading location 0xFFFFFFFF.
In the first function you compare a character in pointer str plus 1 with '\0' The condition can be equal to true only if char is equivalent to signed char and the internal code of *str is equal to 255 (-1).
void revReq(char* str)
{
if((*str+1) != '\0')
revReq(str+1);
putchar(*str);
}
The valid code will look
void revReq( const char *s)
{
if( *str )
{
revReq( str + 1 );
putchar( *str );
}
}
The second function is also wrong. At least you have to write
char* retVal = new char[strlen(str) + 1];
instead of
char* retVal = new char[strlen(str)]+1;
Also there is a memory leak. The function has to return the reversed string.
The valid code will look as
char * rev( const char *s )
{
size_t n = strlen( s );
char *p = new char[ n + 1];
const char *s1 = s + n;
char *q = p;
while ( s1 != s ) *q++ = *--s1;
*q = '\0';
return p;
}
Use strlen(str) + 1
The strlen function returns the size of the string not including the null character '\0'