c++: write a char at a given char* causes segfault - c++

I want to copy a char to an address where a given char* points to.
it's in a function which is called by main:
char data = " ";
myfunction(data, somethingelse);
...
inside the function i have something like
void myfunction(char* data, short somethingelse) {
...
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++;
...
}
the segfault also comes when i to the copy using strncpy:
strncpy(data, byte, 1);
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array. i've tested that multiple times.
thanks in advance.

String literals are readonly. If you want a modifyable string, you must use an array, e.g.:
char data[10];
Or:
char *data = new char[10];
To elaborate a bit more: the type of a string literal is actually const char*. Assigning a string literal to a non-const char* is therefore technically invalid, but most compilers allow it anyway for legacy reasons. Many modern compilers will at least issue a warning when you try to do that.

data is assigned a string literal. String literals are ready only, and writing to them will cause segfaults.
Try this:
char data[10]; // or whatever size you want.
instead.

why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array.
You didn't allocate anything. char *data = " "; shouldn't even compile in C++. You are assigning a constant string to a non-constant.

char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++; // << How many times?
No problem
#include <stdio.h>
int main(int argc, char **argv)
{
char *data = "Yello"; // or char data[] = "Yello";
*data = 'H';
puts(data); // Hello
}

Related

Building / Merging character array pointers in C++

I'm very new to C++ (coming from C#) and it's giving me puzzles :S
I have a very basic question about arrays and it's pointers.
So if I have the following code:
char * test1 = "com";
char * test2 = "ment";
I found similar code in some files already. I don't exactly understand how a string can fit in one character.. but ok...
However, how could I connect these arrays so that I get "comment" ?
I'm pretty sure this char * result = test1 + test2; would only increase the pointer which would then point to something in the memory, which I dont intend to use.
So is it possible to get an array like char array[] = {'c', 'o', 'm', 'm', 'e', 'n', 't'}; back from this?
or can I at least get a pointer which points to something like comment\NUL in the memory?
As you pointed out, pointer arithmetic can't solve this.
If you want to have a C-string as the result, allocating space for the whole new string is required, then copying over the characters, typically using strcat / strncat, but they are C-style string operations.
// Your C-strings
const char *test1 = "com";
const char *test2 = "ment";
// Dynamic allocation of memory for result string
char *result = new char[strlen(test1) + strlen(test2) + 1];
// Start with the empty string
*result = '\0';
// Concatenate both input strings (use strncat if you don't know
// for sure that they will fit into the result array!)
strcat(result, test1);
strcat(result, test2);
// (use result pointer)
// Free the memory after last usage
delete[] result;
In C++, you typically try to avoid them and use std::string instead. Even if you want a C-string as the result, you can use a temporary std::string for allocation and management of the required memory as well as for performing the concatenation:
// Your C-strings
const char *test1 = "com";
const char *test2 = "ment";
// Wrap in temporary C++ strings and concatenate:
std::string result = std::string(test1) + std::string(test2);
// Get the pointer (only valid as long as result is in scope!)
const char *ptr = result.c_str();
Furthermore, please note that you should not assign a string literal to a non-const char * pointer, use a const char* pointer instead. And try to avoid dealing with raw C-strings as long as possible; of course when you use C libraries you have to use them a lot.
Note also that above mentioned methods are performed at runtime; you can't get a compile-time solution for concatenating two string literals, even though the compiler could know what you want to have. I don't know your context, but maybe you only want to have a multi-line string literal, then simply drop the + and write "com" "ment".
A c style solution can be found in the following link:
http://www.cplusplus.com/forum/beginner/5681/:
int len = strlen(test1)+strlen(test2);
char* result = new char[len +1]; // +1 for null terminated string
snprintf(result,len +1, "%s%s",test1,test2);
result[len] = NULL;
// use result
delete(result);
You can utilize std::string:
#include <iostream>
int main() {
// Note: the character literals are const (non const is deprecated)!
const char * test1 = "com";
const char * test2 = "ment";
// This gives a compiler error (there is no way to add pointers)
// const char * concat = test1 + test2;
// A std::string has an overload for the operator +:
std::string comment = std::string(test1) + test2;
// The dynamically allocated string.
// Note: as soon as the comment string gets altered or destroyed the
// pointer s to the internal string data (may) become invalid.
const char* s = comment.c_str();
std::cout << s << '\n';
}

Simple serialization example in c++

I have the following struct:
typedef struct{
int test;
std::string name;
} test_struct;
Then, I have the following code in the main function:
int main(int argc, char *argv[]){
test_struct tstruct;
tstruct.test = 1;
tstruct.name = "asdfasdf";
char *testout;
int len;
testout = new char[sizeof(test_struct)];
memcpy(testout, &tstruct, sizeof(test_struct) );
std::cout<< testout;
}
However, nothing gets printed. What's wrong?
sizeof(std::string) yeilds same value always. It will not give you the runtime length of the string. To serialize using memcpy, either change the struct to contain char arrray such as char buffer[20] or compute the size of the required serialized buffer by defining a method on the struct which gives the runtime length of the bytes.
If you want to use members like std::string, you need to go through each member of the struct and serialize.
memcpy(testout, (void *)&tstruct.test, sizeof(int) );
memcpy(testout+sizeof(int), tstruct.name.c_str(),tstruct.name.length() );
memcpy against the entire struct will not work in such scenarios.
Try NULL-terminating the string and also emitting a newline:
testout = new char[sizeof(test_struct) + 1];
memcpy(testout, &tstruct, sizeof(test_struct));
testout[sizeof(test_struct)] = '\0';
std::cout<< testout << std::endl;
However, as user3543576 points out, the serialization you get from this process won't be too useful, as it will contain a memory address of a character buffer, and not the actual string itself.

Converting a string to char*

I am trying to write a function to convert a std::string to char* .
The first one I have written was this:
char* $ (string str)
{
char* cstr;
const unsigned int length=str.size();
cstr=new char[1000];
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
But the problem was the memory leak: let's suppose that I do this:
char* cstr;
string str1("hello"),str2("hello2");
cstr=$(str1);
cstr=$(str2);
There is a memory leak in this case.The first allocated string is not reachable but it's reference is lost.
So I made the same using static:
char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
But the problem now is that the static char fields are accessible:
char* cstr;
string str("hello");
cstr=$(str);
$(str)[5]='!';
This is possibile, the 6th character is modified and so also the C-style string pointed by cstr is modified.
Using const:
const char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
The problem is that a char pointer is not compatible with a const char pointer, so I can't do this:
string str("hello");
char* cstr;
cstr=$(str);
But I can only use a const char pointer.
What I would do is to have a function which the return value could be placed only as right operand, but not as left operand of an assignment.How could this be done?
I tried to do this:
char* toCharArray(string& str)
{
std::unique_ptr<char>p(new char[1000]);
char* temp=p.get();
for(unsigned int i=0;i<str.size();i++)
{
*temp=str[i];
temp++;
}
return p.get();
}
But the problem is still there, I don't see the difference between this and the other solution I posted using static.Since a code like this:
char* cstr;
string str("hello");
cstr=toCharArray(str);
toCharArray(str)[0]='o';
cout << cstr;
Modifies the string (prints "oello").
Problem still not solved.
You can prevent memory leaks by returning the allocated array as either std::unique_ptr<char[]> or std::vector<char>; both will release the memory if they are reassigned or go out of scope.
You can get a char* pointer to the contents as ptr.get() or &vec[0] respectively.
By the way, since the length is known, the array length really should be length+1, not 1000. Fixed-sized buffers are an overrun waiting to happen. Also, $ is not a portable name for a function.
http://www.cplusplus.com/reference/string/string/c_str/
Look at the example, specifically:
char * cstr, *p;
string str ("Please split this phrase into tokens");
cstr = new char [str.size()+1];
strcpy (cstr, str.c_str());
You need to create a new char * and copy the contents of the std::string over it.
You can use strcpy.
I don't see why you're surprised by the memory leak. If you're making a copy of something, you've got to put it somewhere.
You can either put all the copies in the same place (running a risk of overflow, and putting the onus of taking a proper copy on the client, or they run the risk of unexpected corruption), or you do the allocation (they still have to do the freeing, but at least they don't have to copy), or you get them to pass a buffer and a size into your function.
And seriously, $ as a function name?
What about str.c_str()? Or strdup(str.c_str()) if you want a copy.

How to concat two const char*?

I am not able to concat two const char*.
I do the following:
const char* p = new char[strlen(metadata.getRoot())+strlen(metadata.getPath())];
strcat(const_cast<char*>(p),metadata.getRoot());
strcat(const_cast<char*>(p),metadata.getPath());
strcpy(const_cast<char*>(args2->fileOrFolderPath),p);
function(args2->fileOrFolderPath);
Now when I print the variable args2->fileOrFolderPath on the console then the correct output appears... But when I call a method with the variable as parameter, and work with the variable then I got a segmentation fault. What is the problem?
I did not declare them like this but i know they have this information
So, I have this:
const char* ruta1 = "C:\\Users\\Deivid\\Desktop\\";
const char* ruta2 = "lenaGris.xls";
Then I used this for concatenation:
char * RutaFinal = new char[strlen(ruta1) + strlen(ruta2) + 1];
strcpy(RutaFinal, ruta1);
strcat(RutaFinal, ruta2);
printf(RutaFinal);
This worked for me.
I would prefer using std::string for this, but if you like char* and the str... functions, at least initialize p before using strcat:
*p = 0;
BTW:
using std::string, this would be:
std::string p = std::string(metadata.getRoot()) + metadata.getPath();
strcpy(const_cast<char*>(args2->fileOrFolderPath), p.c_str());
function(args2->fileOrFolderPath);
And you don't have to deallocate p somewhere.
1.
const char* p=new char[strlen(metadata.getRoot())+strlen(metadata.getPath())+1];
the length plus 1 to store '\0'.
2.
strcpy(const_cast<char*>(args2->fileOrFolderPath),p);
You can not guarantee args2->fileOrFolderPath 's length is longger than strlen(p).
This works well
#include <iostream>
using namespace std;
void foo(const char*s){
cout<<s<<endl;
}
int main(int argc,char*argv[]){
const char* s1 = "hello ";
const char* s2 = "world!";
const char* p = new char [strlen(s1)+strlen(s2)+1];
const char* s = new char [strlen(s1)+strlen(s2)+1];
strcat(const_cast<char*>(p),s1);
strcat(const_cast<char*>(p),s2);
strcpy(const_cast<char*>(s),p);
cout<<s<<endl;
foo(s);
return 0;
}
You have char pointers, pointing to char constants which can't be modified . What you can do is to copy your const char array to some char array and do like this to concate const strings :
char result[MAX];
strcpy(result,some_char_array); // copy to result array
strcat(result,another_char_array); // concat to result array
I believe you need to include space for the null terminator, and the first parameter to strcat shouldn't be const as you're trying to modify the memory being pointed to.
You want to do something like this:
char * str1 = "Hello, ";
char * str2 = "World!\n";
char * buffer = malloc(strlen(str1) + strlen(str2) + 1);
strcpy(buffer, str1);
strcat(buffer, str2);
printf(buffer);
Which prints out "Hello, World!" as expected.
As for the error you're seeing when using a parameter, I've wrote some tests to see why it doesn't break when using a const local variable. While compiling using a const char * for the pointer I'm using as the target I get this warning:
./strings.c:10: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
As it states, const is discarded and it works as expected. However, if I pass a parameter which is a const char * pointer, then I get a bus error when trying to modify the buffer it writes to. I suspect what is happening is that it ignores the const on the argument, but it can't then modify the buffer because it's defined as const elsewhere in the code.

Bus Error on Intel Mac, why?

Test program which causes a EXC_BAD_ACCESS signal.
Why does this cause a bus error? I want to change the 'HI' to 'fI'.
//BUS ERROR TEST
#include <iostream>
void test(char *text)
{
text[0] = 'f';
}
int main()
{
char *text = (char *)"HI";
test(text);
std::cout << text << std::endl;
return 0;
}
You are not allowed to change string constants, that's undefined behaviour as per the standard.
If you replace:
char *text = (char *)"HI";
with something like:
char text[3];
strcpy (text, "HI");
or:
char text[] = "HI";
you'll find that it will work, because text in that case is modifiable memory.
You must not cast away const, it's UB. The string constants are read-only, so the compiler is allowed to put them into read-only memory.
Use
char text[] = "Hi!";
to get a modifiable string.
char *text = (char *)"HI";
text[0] = 'f';
This is actually against the C++ standard. Quoted strings are declared const for a reason. In your case, it probably stores the string as part of your "code data" rather than regular "data". This, combined with the common usage of making the "code data" area read only makes it so that you won't be able to write to quoted constant strings.