I am getting "Access violation" error but unable to identify the root cause for it . I am new to c++ and preparing for C++ coding contest as a beginner. Please help me to get the root cause for it. Please find the attached screenshot.
Thanks in advance .
Here is my code in a single .cpp file.
#include <iostream>
using namespace std;
void reverse(char *str) {
char * end = str;
char tmp;
if (str) {
while (*end) {
++end;
}
--end;
while (str < end) {
tmp = *str;
*str++ = *end; //Getting exception here
*end-- = tmp;
}
}
}
int main ()
{
char *str="Test";
cout << "Before change"<<str; // prints Hello World!
reverse(str);
cout << "After change"<<str; // prints I'm a C++ program
getchar();
}
You are getting a segmentation fault, because you are trying to edit the read-only memory where the literal string "Test" is stored (since string literals are const char* in c++).
In order to make your code run, you can store the literal string in a char array so the first line in main() will look like this:
char str[] = "Test";
The problem is that the type of string constants by default in C++ is const char *.
In the following line, you assign a non-const char * to a const char *.
char *str="Test";
Thus, when you pass this variable to the reverse function, you are attempting to write to read-only memory. This violates the rules of C++, and leads to unexpected behaviour.
Define your string like this instead to solve the problem:
char str[] = "Test";
This gives you the ability to modify the string, as it isn't a const anymore.
Related
I keep getting a SIGSEGV crash converting a std::string to char*. I have a name I wish to display in an ITextControl (WDL Framework). The following snippet works fine in some parts of my app but not here:
char * paramName = new char[name.size() + 1];
std::copy(name.begin(), name.end(), paramName);
paramName[name.size()] = '\0'; // don't forget the terminating 0
lcdToWriteParamNamesTo->SetTextFromPlug(paramName);
Following the trace....
void ITextControl::SetTextFromPlug(char* str)
{
if (strcmp(mStr.Get(), str))
{
SetDirty(false);
mStr.Set(str);
}
}
Next step:
char *Get()
{
if (m_hb.GetSize()) return (char *)m_hb.Get();
static char c; c=0; return &c; // don't return "", in case it gets written to.
}
And finally CRASH!:
int GetSize() const { return m_size; }
EDIT: As requested:
void WDL_STRING_FUNCPREFIX Set(const char *str, int maxlen WDL_STRING_DEFPARM(0))
{
int s=0;
if (str)
{
if (maxlen>0) while (s < maxlen && str[s]) s++;
else s=(int)strlen(str);
}
__doSet(0,str,s,0);
}
From my limited understanding of C++ and this answer, a bounds issue could cause the SIGSEGV or writing into read-only memory.
Just to clarify, this snippet in one class ALWAYS crashes and in another class NEVER crashes, though both classes are passed the same string and ITextControl.
Can anybody help me shed some light on this?
EDIT: Suggestion to use c_str() doesn't help:
char * cstr = new char [name.length()+1];
std::strcpy (cstr, name.c_str());
lcdToWriteParamNamesTo->SetTextFromPlug(cstr);
delete[] cstr;
This also crashes.
Doesn't look like converting string is an issue.
SIGSEGV is triggered on invalid memory reference.
It means when you try to read from
lcdToWriteParamNamesTo->mStr->m_hb->m_size you read from not acquired memory.
One of objects is probably already destroyed or by mistake one of pointers is overwritten to point to memory not acquired:
lcdToWriteParamNamesTo
mStr
m_hb
m_size
Below is my sample code. Its just a sample which is similar to the code which i'm using in my applicaiton.
#define STR_SIZE 32
void someThirdPartyFunc(const char* someStr);
void getString(int Num, const char* myStr)
{
char tempStr[] = "MyTempString=";
int size = strlen(tempStr) + 2;
snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}
int main()
{
const char * myStr = new char(STR_SIZE);
getString(1, myStr); // get the formated string by sending the number
someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
delete myStr;
return 0;
}
I am getting an exception if i use this code. I think the problem is with deleting the "myStr". But delete is really necessary.
Is there any other way to format the string in getString and send it to the ThirdPartyFunc??
Thanks in advance.
you are allocating not an array of chars but one char with this line:
const char * myStr = new char(STR_SIZE);
and that one allocated char is initialized with the value of STR_SIZE, causing a "char overflow" in this case.
if you want an array of size STR_SIZE:
const char * myStr = new char[STR_SIZE];
(note the rectangular [ ]). you have to deallocate such allocated chunk of memory by using the delete[] operator.
personal note: the code you have written above (manually allocated strings etc) is good educational wise; you will do a lot of such mistakes and thus learn about the inner workings of C / C++. for production code you do not want that, for production code you want std::string or other string-containers to avoid repeating string-related mistakes. in general you are not the one who sucessfully reinvent how string-libraries will work. the same is true for other container-types like dynamically-growable-arrays (std::vector) or dictionary-types or whatever. but for educational fiddling around your code above serves a good purpose.
there are other problems in your code snippet (handing over const char* to a function and then modifying the ram, not calculating correctly the size parameter when calling snprintf etc), but these are not related to your segfault-problem.
Re the technical, instead of
const char * myStr = new char(STR_SIZE);
do
char const myStr[STR_SIZE] = "";
Note that both have the problem that the string can’t be modified.
But you only asked about the allocation/deallocation problem.
But then, there's so much wrong at levels above the language-technical.
Here's the original code, complete:
void someThirdPartyFunc(const char* someStr);
void getString(int Num, const char* myStr)
{
char tempStr[] = "MyTempString=";
int size = strlen(tempStr) + 2;
snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}
int main()
{
const char * myStr = new char(STR_SIZE);
getString(1, myStr); // get the formated string by sending the number
someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
delete myStr;
return 0;
}
Here's how to do that at the C++ level:
#include <string> // std::string
#include <sstream> // std::ostringstream
using namespace std;
void someThirdPartyFunc( char const* ) {}
string getString( int const num )
{
ostringstream stream;
stream << "MyTempString=" << num;
return stream.str();
}
int main()
{
someThirdPartyFunc( getString( 1 ).c_str() );
}
The #define disappeared out of the more natural code, but note that it can very easily lead to undesired text substitutions, even with all uppercase macro names. And shouting all uppercase is an eyesore anyway (which is why it's the macro name convention, as opposed to some other convention). In C++ simply use const instead.
I am trying to reverse a null terminated string in place in C++. I have written the code below:
//Implement a function to reverse a null terminated string
#include<iostream>
#include<cstdlib>
using namespace std;
void reverseString(char *str)
{
int length=0;
char *end = str;
while(*end != '\0')
{
length++;
end++;
}
cout<<"length : "<<length<<endl;
end--;
while(str < end)
{
char temp = *str;
*str++ = *end;
*end-- = temp;
}
}
int main(void)
{
char *str = "hello world";
reverseString(str);
cout<<"Reversed string : "<<str<<endl;
}
However, when I run this C++ program , I get a a write access violation inside the while loop at the statement : *str = *end ;
Even though this is fairly simple, I can't seem to figure out the exact reason I am getting this error.
Could you please help me identify the error?
char *str = "hello world";
is a pointer to a string literal, and can't be modified. String literals reside in read-only memory and attempting to modify them results in undefined behavior. In your case, a crash.
Since this is clearly an assignment, I won't suggest using std::string instead, since it's good to learn these things. Use:
char str[] = "hello world";
and it should work. In this case, str would be an automatic-storage (stack) variable.
I've got a character from the keyboard, by integer:
int c = getch();
an I want to append it to a string only if it isn't a return:
void somefunction()
{
std::string str = "you pressed: ";
int c;
while ( 1 )
{
c = getch();
if ( c == 10 ) break;
char* ch;
sprintf(ch,"%c",c);
str += std::string(ch);
}
}
however, this creates a segmentation error when the scope of somefunction is left. I'm geussing that when the dtor for str is called the pointer to ch isn't available any more.
How can I remedy this?
This is much easier than you think:
str.push_back(c);
You are getting segmentation fault, because you are trying to sprintf string into unknown (not yet allocated) memory:
char* ch;
sprintf(ch,"%c",c);
possible fix of your code would be to replace char* ch; with char ch[2]; which would cause ch to become an statically allocated array with an automatic storage duration.
But note that since you are programming in C++ it would be wiser to use streams and methods of std::string rather than C-style (char*) strings and C-style functions like sprintf.
I am writing a very simple program that removes duplicate chars from a string. I ran it visual studio and got the error:
Unhandled exception at 0x00d110d9 in inteviews.exe: 0xC0000005: Access violation writing location 0x00d27830.
I really don't see what the problem is. current cell gets the value of the next cell.
void remove(char *str, char a) {
while (*str != '\0') {
if (*(str+1) == a) {
remove(str + 1, a);
}
*str = *(str +1 );//HERE I GET THE ERROR
++str;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char *str = "abcad";
while (*str != '\0') {
remove(str,*str);
str++;
}
std::cout << str << std::endl;
return 0;
}
EDIT:
I already tried to change it to char str[] = "abcad" but I still get the same error.
You're attempting to modify a string literal. You can't do that.
char *str = "abcad";
That's a string literal. It's created in read-only memory therefore attempting to write to it is an access violation.
One problem is that you created a read-only string literal and attempted to modify it:
char *str = "abcad"; // String literals are read-only!
You could use a char array instead:
char str[] = "abcad";
There are all sorts of problems with your program. I begun by trying to write them all down but I feel that code is irredeemable. It has indexing errors, parameter passing errors, dubious recursion and so on.
The other answers that point out the error of trying to modify a read-only literal are correct. That is the cause of the error in the code you posted.
The main reason for your troubles, in my view, is that the code is harder to write when you only have a single buffer. You have tied yourself in knots trying to get around this limitation in your design, but with a second buffer to work with, the code is trivial.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *input = "abcad";
char *output = malloc(strlen(input)+1);
char *in = input;
char *out = output;
while (*in)
{
if (*in != input[0])
{
*out = *in;
out++;
}
in++;
}
*out = '\0';
printf("%s\n", output);
free(output);
return 0;
}
If you want to get really clever you can in fact manage happily with just a single buffer, so long as you keep two distinct pointers for iteration.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = "abcad";
char compare = str[0];
char *in = str;
char *out = str;
while (*in)
{
if (*in != compare)
{
*out = *in;
out++;
}
in++;
}
*out = '\0';
printf("%s\n", str);
return 0;
}
Note that we had to take a copy of first character in the buffer, the character being removed, since that may be modified by the iteration.
So now you are back where you started, with a single buffer. But now the code works and is easy to understand.
Note that my answer is written in C as per your tag, but note that your code is C++.
Since string literal is created in read-only memory, attempting to write to it is an access violation. What you can do is strcpy(dst, src) to a character array.
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
char *str = "abcad";
char str2[10];
strcpy(str2, str);
while (*str2 != '\0') {
remove(str2, *str2);
str2++;
}
}