When does character and int concatenation result in seg fault? - c++

#include <iostream>
#include <string>
using namespace std;
int main()
{
int number = 900;
cout << std::string("Hello, World!" + number) << std::endl;
return 0;
}
I know the correct solution will be to use std::to_string(number). But the question here is, why do I not get a segmentation fault? I even ran it through valgrind. The string length is around 13 and I move the pointer 900.

The expression "Hello, World!" + number is a const char[] literal added to an int. The former decays to a const char* pointer and you add number to it by pointer arithmetic.
Since that final pointer is not in the original string constant, you are passing an invalid const char* pointer to a std::string constructor, and the behaviour of your program is undefined. Anything can happen at that point, including a runtime crash. An aggressively optimising compiler might omit the undefined expression altogether; that's getting progressively more common.
Boom!
If you wanted to concatenate 900 to the string, then you could have written
std::cout << std::string("Hello, World!" + std::to_string(number)) << std::endl;

Related

Why doesn't while (*s++=*t++); work for me?

I came across this function on a blog and I found it really cool. I understand how it works conceptually since C++ was my first language.
However, when I tried actually writing it out in a program of mine, it doesn't seem to work. I've googled all over but I've only found explanations as to how it works so I've been really stumped.
Instead of copying the NULL char[5] (which should evaluate to false, copy nothing and break the loop), it gives two compilation errors, saying that "I can't increment value of type char[6]" (out-of-bounds error for both arrays).
Why doesn't my loop break at char[5]?
I'm guessing it's something to do with the subtleties of char and string, I tried initialising strings instead with cstring included, that didn't work either, the similar error of "cannot increment type string" shows up.
#include <iostream>
using namespace std;
int main () {
char s[] = "hello";
char t[] = "house";
while (*s++ = *t++);
cout << s;
return 0;
}
You can't increment an array. What would that even mean?
Try this:
#include <iostream>
using namespace std;
int main ()
{
char s[] = "hello";
char t[] = "house";
char *ss = s;
char *tt = t;
while (*ss++ = *tt++);
cout << s << endl;
}
The line " while (*ss++ = *tt++) " is always going to be true, because = is the assignment operator. You probably want " while (*ss++ == *tt"")", which compares equality.

const char* to int cast?

I suppose the behaviour of the following snippet is supposed to be undefined but I just wanted to make sure I am understanding things right.
Let's say we have this code:
#include <iostream>
int main()
{
std::cout << "mamut" - 8 << std::endl;
return 0;
}
So what I think this does is (char*)((int)(const char*) - (int)), though the output after this is pretty strange, not that I expect it to make any real sense. So my question is about the casting between char* and int - is it undefined, or is there some logic behind it?
EDIT:
Let me just add this:
#include <iostream>
int main ()
{
const char* a = "mamut";
int b = int(a);
std::cout << b << std::endl;
std::cout << &a <<std::endl;
// seems b!= &a
for( int i = 0; i<100;i++)
{
std::cout<<(const char*)((int)a - i)<<std::endl;
}
return 0;
}
The output after i gets big enough gives me a something like _Jv_RegisterClasses etc.
Just for the record:
std::cout << a - i << std::endl;
produces the same result as:
std::cout<<(const char*)((int)a - i)<<std::endl;
There is no cast, you are merely telling cout that you want to print the string at the address of the string literal "mamut" minus 8 bytes. You are doing pointer arithmetic. cout will then print whatever happens to be at that address, or possibly crash & burn, since accessing arrays out of bounds leads to undefined behavior.
EDIT
Regarding the edit by the op: converting an address to int doesn't necessarily result in a correct number identical to the address. An address doesn't necessarily fit in an int and on top of that, int is a signed type and it doesn't make any sense to store addresses in signed types.
To guarantee a conversion from pointer to integer without losses, you need to use uintptr_t from stdint.h.
To quote the C standard 6.3.2.3 (I believe C++ is identical in this case):
Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
There is no casting going on. "mamut" is a pointer to characters, and - 8 will do pointer arithmetic on it. You are right that it's undefined behavior, so even though the semantic behavior is pointer arithmetic, the runtime behavior can be literally anything.
You are printing string starting from address of "mamut" minus 8 bytes till null terminator i.e. in total 8+5 = 13 chars

what is wrong with this program?

#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string x;
getline(cin,x);
ofstream o("f:/demo.txt");
o.write( (char*)&x , sizeof(x) );
}
I get the unexpected output.I don't get what i write in a string function.
Why is this ?
Please explain .
Like when i write steve pro i get the output as 8/ steve pro ÌÌÌÌÌÌ ÌÌÌÌ in the file
I expect that the output be steve pro
You are treating an std::string like something that it is not. It's a complex object that, somewhere in its internals, stores characters for you.
There is no reason to assume that a character array is at the start of the object (&x), and the sizeof the object has no relation to how many characters it may indirectly hold/represent.
You're probably looking for:
o.write(x.c_str(), x.length());
Or just use the built-in formatted I/O mechanism:
o << x;
You seem to have an incorrect model of sizeof, so let me try to get it right.
For any given object x of type T, the expression sizeof(x) is a compile-time constant. C++ will never actually inspect the object x at runtime. The compiler knows that x is of type T, so you can imagine it silently transforming sizeof(x) to sizeof(T), if you will.
#include <string>
int main()
{
std::string a = "hello";
std::string b = "Stack Overflow is for professional and enthusiast programmers, people who write code because they love it.";
std::cout << sizeof(a) << std::endl; // this prints 4 on my system
std::cout << sizeof(b) << std::endl; // this also prints 4 on my system
}
All C++ objects of the same type take up the exact amount of memory. Of course, since strings have vastly different lengths, they will internally store a pointer to a heap-allocated block of memory. But this does not concern sizeof. It couldn't, because as I said, sizeof operates at compile-time.
You get exactly what you write: the binary raw value of a pointer to char...
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string x;
getline(cin,x);
ofstream o("tester.txt");
o << x;
o.close();
}
If you insist on writing a buffer directly, you can use
o.write(x.c_str(), x.size());
PS A little attention to code formatting unclouds the mind
You're passing the object's address to write into the file, whereas the original content lies somewhere else, pointed to by one of its internal pointers.
Try this:
string x;
getline(cin,x);
ofstream o("D:/tester.txt");
o << x;
// or
// o.write( x.c_str() , x.length());

Strange use of strlen

I tried to compile the follow sample code:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
int main ()
{
if (strlen <= 0) {
cout << "trace1" << endl;
return 0;
}
cout << "trace2" << endl;
return 0;
}
The strange thing is that it compiles successfully. Do you have any idea why?
I have not declare the strlen as variable.
Using just the identifier of a function decays to a function pointer of the corresponding type. In this case, strlen is a pointer of the type size_t (*)(const char *). This pointer holds the address of the first instruction of the function in the executable code.
Testing the value of that pointer is legal, whatever the reason may be, although it seems strange in the code fragment you have provided.
strlen without the () gives you a function pointer to the address where the strlen function is allocated in memory.
The program prints "trace1" if the library function strlen is allocated at an address less than 0, which is impossible on every computer in the world, or if it is allocated at address 0 (extremely unlikely but possible). Otherwise, if strlen is allocated at an address that is larger than zero (most likely the case), it prints "trace2".
It's probably decays into an address which decays into an integer. A real compiler will probably fill the screen with warnings.
If you do the same with other functions than strlen, this sample code will print trace2 because strlen is a pointer to function size_t strlen ( const char * str ) and it's value should be a positive number.
cout << (size_t *) strlen << endl;
cout << (size_t *) strcat << endl;
for example the code above prints:
0x7fff84d29110
0x7fff84d63953
on my machine (as you see these are positive numbers because they are started with 7).
Also if I print strlen and strcat without casting to (size_t *) the result will be 1 which means that these functions are valid.

Cstring in C++ - using standard C functions leading to a segmentation fault [duplicate]

This question already has answers here:
What is a segmentation fault?
(17 answers)
Closed 4 years ago.
for certain functions i want to create a copy of the string within the function and then manipulate this - for some strange reason, i cant get strcpy to work (gives me a segmentation fault) - i've also tried passing the arg as a string, this doesnt work either (g++ throws an error saying it expect a char*)
#include <iostream>
#include <cstring>
using namespace std;
void copy_string(char* stri);
int main ()
{
copy_string("sample string");
return 0;
}
void copy_string(char* stri) {
char* stri_copy;
strcpy(stri_copy, stri);
cout << "String: " << stri_copy;
}
im not sure i understand why this is happening.
so my two questions are:
why this is occuring - is there an easy fix?
whats the simplest / most efficient way of creating a local copy of a string passed to a function?
thanks!
char* stri_copy;
stri_copy = (char*)malloc(strlen(stri) * sizeof(char) + 1);
strcpy(stri_copy, stri);
You aren't allocating space for stri_copy.
The pointer to stri_copy has not been malloc'd. Using strdup below will solve the problem and allocate the memory accordingly for the value of stri.
char* stri_copy;
stri_copy = strdup(stri);
Hope this helps,
Best regards,
Tom.
I don't know if this is what you're looking for but I got it to work with strings.
#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;
void copy_string(string);
int main ()
{
copy_string("sample string");
return 0;
}
void copy_string(string stri) {
string cpy = stri;
cout << "String: " << cpy;
}
char* stri_copy;
strcpy(stri_copy, stri);
The problem is that stri_copy does not point to valid memory. strcpy first parameter expects the proper memory location.
int len = strlen(stri);
char* stri_copy = new char[ len + 1];
strncpy(stri_copy, stri, len );
stri_copy[len] = '\0';
To use strcpy, you need a buffer of allocated memory as a target. Your stri_copy pointer is not pointing to such a buffer.
You have a segmentation fault because stri_copy does not point to valid memory.
If you can use the STL, then you can have a way to do this:
void copy_string(const std::string& stri) {
char* stri_copy= stri.c_str();
// work with the copy of the string
std::cout << "String: " << stri_copy;
}
The std::string makes a copy of the string parameter and disposes of the copy for you after you've finished with it.
Edit: Used const std::string& as the parameter type.
strcpy does not allocate any storage to hold the result. You're using a "random" pointer as the destination which is why you are seeing segfaults. A very simple implementation of strcpy would look like
void naivestrcpy(char* destination, const char* source) {
while(*source) *destination++ = *source++;
*destination = 0;
}
strcpy does exactly what it says on the tin, it copies. It does not ensure you've loaded the right size of paper into the xerox tray.