C++ Array Iteration - c++

Can anyone spot the reason why nothing gets printed onto console using below C++ code;
string array[] = { "a", "b", "c", "d" };
int length = sizeof(array);
try
{
for (int i = 0; i < length; i++)
{
if (array[i] != "") cout << array[i];
}
}
catch (exception &e)
{
e.what();
}

You use the wrong length:
int length = sizeof(array)/sizeof(array[0])
The actual reason you don't see anything on the console is because the output is buffered, and since you haven't wrote a newline it's not flushed. In the meantime your app crashes.

No end of line character.
Also as mentioned by Dave, sizeof is not the length of the array

This answer assumes that string == std::string.
let T be an arbitrary type, and n be an arbitrary positive integer - then:
sizeof(T[n]) == n * sizeof(T)
That is - sizeof(array) is not the length of the array, but the total amount of memory used by the array (in chars). Your std::string implementation could very well be using more than 1 char's worth of memory to store its structure. This leads to length holding a value much greater than 4.
This causes the program to read from past the end of array; an operation for which C++ imposes no requirements (it is Undefined Behaviour).
In terms of the C++ abstract machine, a program containing Undefined Behaviour can do absolutely anything, even before the point in the execution of the program at which the Undefined Behaviour was encountered. In your particular case your program exhibits this behaviour by not printing anything (even though you had made 4 well defined calls to operator<< before the erroneous array indexing).
You have tagged this eclipse-cdt, so I will assume that you are using GCC to compile your program, and are running it under a modern operating system with memory-protection. In this case the actual reason for the behaviour that you are seeing is probably that std::cout is buffering the first few strings that you stream into it and so not immediately printing them to the console. After that you get to the buffer overrun and your operating system interrupts the process with a EXC_BAD_ACCESS signal or similar. This causes the immediate termination of your program, which does not give std::cout a chance to flush its buffered values. All up, this means that nothing gets printed.
As mentioned in another answer, you should replace the line:
length = sizeof(array);
with:
length = sizeof(array)/sizeof(array[0]);
This will guarantee that length will hold the value 4, rather than the value 4 * sizeof(string), that could be many times the length of the array.

Related

strncat undefined behaviour on particular number

I know the size of destination is small so that my code not working correctly but all I want to know when I put 35 in destination character print in infinite loop why it become infinite only when I put 35 in other number it crash or work in bigger number.
I am using Windows 7 Code Block with gcc.
using namespace std;
int main()
{
char dest[35] = "This is an example";//when put another number it work or crash but at this number it print infinite number of character why what is logic
char src[50] = " to show working of strncat() this is not added";
strncat(dest, src, 29);
cout << dest ;
return 0;
}
You have 17 characters plus a null byte in the initialized dest array.
When you call strncat(dest, src, 29), you say "it is safe to add 29 extra characters to dest" — which is nonsense as you can only add 17 characters without overflowing the array.
You invoked undefined behaviour. That means the program can work, or crash, or go into an infinite loop, and all those behaviours are OK because undefined behaviour doesn't have to behave in any specific way.
Note that strncat(dst, sizeof(dst), very_long_string) is a boundary error, even if dst[0] == '\0'. You can use strncat(dst, sizeof(dst)-1, very_long_string) if the destination is empty. (The very long string is any string longer than sizeof(dst) - 1, of course.)

Trouble Understanding sprintf with 'char * str + int'

I was looking at a project and came across the following code and am unable to figure out what the sprintf is doing in this context and was hoping someone might be able to help me figure it out.
char storage[64];
int loc = 0;
int size = 35;
sprintf(storage+(loc),"A"); //Don't know what this does
loc+=1;
sprintf(storage+(loc),"%i", size); //Don't know what this does
loc+=4;
sprintf(storage+(loc), "%i", start); //Don't know what this does
start += size;
loc += 3;
The code later does the following in another part
string value;
int actVal;
int index = 0;
for(int j = index+1; j < index+4; j++)
{
value += storage[j];
}
istringstream iss;
iss.str(value);
iss >> actVal; //Don't understand how this now contains size
The examples I have seen online regarding sprintf never covered that the above code was possible, but the program executes fine. I just can't figure out how the "+loc" affects storage in this instance and how the values would be saved/stored. Any help would be appreciated.
Ugly code! Regardless, for the first part, storage+(loc) == &storage[loc]. You end up with a string "A35\0<unknown_value>1234\0", assuming start = 1234, or in long form:
sprintf(&storage[0],"A");
sprintf(&storage[1],"%i", size);
sprintf(&storage[5], "%i", start);
For the second part, assuming we have the "A35\0<unknown_value>1234\0" above, we get:
value += '3';
value += '5';
value += '\0';
value += '<unknown_value>'; // This might technically be undefined behaviour
So now value = "35". [1]
iss.str(value);
iss >> actVal;
This turns the string into an input stream and reads out the first string representing an integer, "35", and converts it into an integer, giving us basically actVal = atoi(value.c_str());.
Finally, according to this page, yes, reading an uninitialised ("indeterminate value" is the official term) array element is undefined behaviour thus should be avoided.
[1] Note that in a usual implementation, there is a theoretical 10/256 chance that the <unknown_value> could contain an ASCII digit, so value could end up being between 350 and 359, which is obviously not a good outcome and is why one shouldn't ignore undefined behaviour.
The function sprintf() works just like printf(), except the result is not printed in stdout, rather it is store in a string variable. I suggest you read the sprintf() man page carefully:
https://linux.die.net/man/3/sprintf
Even if you are not on a Linux, that function is pretty much similar across different platforms, be it Windows, Mac or other animals. That said, this piece of code you have presented seems to be unnecessarily complicated.
The first part could be written as:
sprintf(storage,"A %i %i", size, start);
For a similar-but-not-equal result, but then again, it all depends on what exactly the original programmer intended this storage area to hold. As Ken pointed out, there are some undefined bytes and behaviors coming from this code as-is.
From the standard:
int sprintf ( char * str, const char * format, ... );
Write formatted data to string
Composes a string with the same text that would be printed if format was used on printf, but instead of being printed, the content is stored as a C string in the buffer pointed by str.
sprintf(storage+(loc),"A");
writes "A" into a buffer called storage. The storage+(loc) is pointer arithmetic. You're specifying which index of the char array you're writing into. So, storage = "A".
sprintf(storage+(loc),"%i", size);
Here you're writing size into storage[1]. Now storage = "A35\0", loc = 1, and so on.
Your final value of storage = "A35\0<garbage><value of start>\0"
actVal: Don't understand how this now contains size
The for loop goes through storage[1] through storage[5], and builds up value using the contents of storage. value contains the string "35\0<garbage>", and iss.str(value) strips it down to "35\0".
iss >> actVal
If you have come across std::cin, it's the same concept. The first string containing an integer value is written into actVal.

Zero termination when casting a char array to string?

I have this simple piece of code which reverses a string:
# include <string>
string str = "abcd";
char *ch = new char[str.length()];
for (int i = 0, j = str.length() - 1; i < str.length(); i++, j--)
ch[j] = str[i];
str = string(ch);
cout << str;
This works fine, however I was wondering if the char array *ch must be zero terminated (perhaps it just works ok. because by chance there happens to be a 0 at memory position ch + str.length(). Therefore I've written the following quick test:
string str = "abcd";
char *ch = new char[str.length()];
for (int i = 0, j = str.length() - 1; i < str.length(); i++, j--)
ch[j] = str[i];
// note: illegal memory access, just a quick test
ch[str.length()] = 'a';
str = string(ch);
cout << str;
In the above code it is ensured that *ch is never zero terminated. To my suprise the code still works ok, I can't get my head around this. How can str = string(ch) result in "dbca" when at ch[str.length] there is 'a'; I would either expect a memory error or "dbcaa" as a result.
It doesn't matter what you did before this line:
str = string(ch);
The reason is that the line above may allocate memory, and the memory manager may have used the memory directly following your ch buffer as allocated space. So the a character you wrote there previously has vanished. Or something else happened during the construction of str that assumed that the space you wrote to previously is available.
If you want to know for sure, use your debugger. The std::string constructor and implementation will tell you what exactly occurred (that is, if your program even gets this far since you did introduce undefined behavior before the line of code above).
It's called undefined behaviour. It could be there is a zero after the last address of ch so it could appear to work. But you're overwriting memory allocated from the memory manager which will corrupt it, so you will run into trouble in a bigger application.
The memory manager could reserve a few more bytes in debug builds for debug purpose. Try a release build and see what happens
You're code is totally broken, having undefined behaviour. Specifically...
ch[j] = ch[i];
...reads from ch[i] which is uninitialised memory - as bgoldst commented it's probably meant to be str[i], then - even if that didn't invalidate any expectations of program behaviour...
str = string(ch);
...attempts construction using a ch, which points to still uninitialised memory that could have any content at all, and will be scanned along until a NUL happens to be hit, some access violation crashes the program, or whatever other undefined behaviour manifests. If you fixed the loop to copy from str, then you'd probably want this to cope with the lack of NUL termination:
str = string(ch, str.length());
Perhaps the vaguely worthwhile question is "isn't it almost impossible that I'd have observed (the claimed) dbca output despite the above errors?". To that I'd say:
dbca is not dcba - which did you actually see?
garbage characters in memory might not do anything on your terminal, and it's quite possible that attempting to print from where ch was allocated printed nothing visible, or e.g. printed some crap then a clear-back-to-the-start-of-line, delete-previous, backspace etc. character code, then happened to hit the memory allocated by the std::string object (seemingly lacking a short-string-optimisation buffer), and therefore displayed its contents too.
So - it's not so statistically amazing to constitute evidence for your program somehow having defined behaviour....

Sizeof is a negative number when I try to find out the length of a string

In my code, I've been trying to find the length of a specific string in a string array. However, when I do it, no matter what method I try to find the length of the specific string, always returns -858993460
The code I've been working with is
void drawChoices(int x, std::string s [], int iChoice)
{
setCurPos(x, 1); //this function just sets the console cursor
for (int i = 0; i <= iChoice; i++)
{
color(15, 4); //this function just sets the console color
std::cout << "[" << s[i] << "]";
color(8, 8);
int asfa = sizeof s[i]; //this is the one causing trouble
std::cout << " \n";
}
}
I tried finding the length of the string in the array with sizeof, string::length, and strlen, but those yielded the same results.
You can never obtain the length of a string with sizeof. The sizeof operator is evaluated at compile time and returns the size of a type or variable. Your use of sizeof is:
sizeof s[i]
Since s[i] has type std::string, that expression evaluates to whatever size your implementation's std::string happens to be. But that is determined at compile time, and so has no dependency on the contents of the buffer, and is something that you are simply not interested in knowing.
Use either std::string::size() or std::string::length() to obtain the length of a std::string.
So, in your code you would use
s[i].length()
to obtain the length, that is the number of character elements, in the string s[i]. Do note also that the size() and length() methods, which are interchangeable, return std::string::size_type which you should use rather than int.
As for where the negative value comes from, we cannot say. Your code doesn't output the value that sizeof yielded, which would not be negative in any case.
Should your loop really be
for (int i = 0; i <= iChoice; i++)
rather than
for (int i = 0; i < iChoice; i++)
Rather than passing, and presumably storing, arrays of std::string, it would be more idiomatic to use a C++ container. In this case std::vector<std::string>.
From what #VladfromMoscow mentioned, I have figured out the problem.
The problem was when I was using Visual Studio 2013's debugging and local windows, I was debugging the same time the variable was initializing.
With the local window compiling the order of the line and how Visual Studio's debugging works, it gives out a random number because the variable wasn't initialized.
It reads size_t asfa first, stops it, local window gets the value, and then executes s[i].length(); once I continue it.
I thought it would be the program's fault because I tried outputting std::cout << asfa;, but I remebered that you can't have an int or size_t to a string directly, without a cast or conversion. Thank you for all of you who helped.

buffer size changed

I am doing a simple communication between sockets and here is my C++ code
while(1)
{
string buffer = "23,45\n";
const char* foo = buffer.c_str();
cout << "size of buffer is " << sizeof(buffer)<<endl;
send (s, foo, sizeof(buffer), 0);
}
weird thing is the fist iteration, the size of the buffer is 5 as expected, but since the second iteration and so on, the size dramatically jumped to 32. any idea why? Thank you very much. By the way, the added size comes from leading while spaces.
The sizeof operator returns the size (in bytes) of the object. It doesn't return the length of a container type. You need to use std::string::length() or std::string::size() to determine the length of the string.
I think you misunderstood the 5 of the first iteration: it must be coming from somewhere else. sizeof(buffer) is figured out at compile time - it is the size of std::string, so you should see 32 on every iteration.
If you are looking for the length of the string, use buffer.size() instead.
sizeof(buffer) tells you the size of your std::string object, which has nothing to do with the number of characters you store in it (which by the way are 7 in your example, not 5).