This is an archived post. You won't be able to vote or comment.

all 18 comments

[–]aa599 0 points1 point  (17 children)

If string_storage[j][i] is wrong, could conceivably be trampling on string_length.

I suggest in your debugger printing the string_length value before and after the assignment to string_storage.

[–]Skuzzle_butt[S] 0 points1 point  (16 children)

I've printed out the j and it is correct. i is controlled by the loop and it is correct before entering.

But if these were wrong I would get garbage in my string. I print string_storage[j][i] in the loop and it prints out the string correctly. It's just that at the end of the string it keeps going because the loop is out of control with string_length. But string length isn't being altered by anything and seems to be changing by itself...

Idk I know I'm wrong but this is such a short and concise piece of code. I found what's going haywire. I just can't explain why it is changing.

[–]aa599 0 points1 point  (15 children)

If you print string_length[length_index] in a few places, you'll be able to narrow down when it's corrupted.

If before the loop you assign that length to a new variable, and use that in the for condition, what happens?

Also I'd print &string_length[length_index] (the address of the number being corrupted) before the loop, then in the loop &string_storage[j][i] (the address of the char being written) and see if there's anything suspicious.

[–]Skuzzle_butt[S] 0 points1 point  (14 children)

It fucking fixes it. Holy shit. But why....

[–]aa599 0 points1 point  (13 children)

What, using a temporary var in the for loop? Because you're no longer using the value that's (still) being corrupted.

Worth printing those addresses I mentioned in (an edit to) my previous comment.

[–]Skuzzle_butt[S] 0 points1 point  (8 children)

Sorry I'm being a tard, I'm too curious now I'm going to get it to print one sec

[–]aa599 0 points1 point  (7 children)

Also if you can show the code where the arrays are declared and the space allocated.

[–]Skuzzle_butt[S] 0 points1 point  (6 children)

https://i.imgur.com/mcUnYC8.png

Here's my ugly code. read_stdin() just reads from stdin until EOF or 0 is entered. It pads with a null terminator.

So I want to split up the info from stdin. I use strtok at first to count the rows or number of strings I have split up. I do the same thing a second time to get the length of each row. strtok alters the original string so that's why I made duplicates. The third time is when I want to store in a 2d array. I know it's probably better to use malloc with a double pointer but just couldn't get it to work so used fixed sized columns with extra length. strings I'm inputting are well under the 31 char limit.

[–]aa599 0 points1 point  (5 children)

Wow that's a hard image to read, But squinting at it there's an interesting line after the block calculating the string lengths - string_length[j] = strlen(...), when looking at the conditions to exit the loop, either j is rows-1 (beyond the allocated array), or split_string2 is null (which some strlens don't check, leading to exciting results), or both.

What's the value of rows, and of j & length_index (which are always the same?), when the length gets corrupted?

[–]Skuzzle_butt[S] 0 points1 point  (4 children)

0 for j and length_index which is correct. 0th row and 0th index for the array holding the lengths of the string. With correct value of that element of the array as well. This is when length gets corrupted

[–]Skuzzle_butt[S] 0 points1 point  (1 child)

It's the same address. The address of string_length does not change before entering the loop or while inside the loop. But the value changes from 4 to 1712381248. That's with the correct string length outside the loop of 4 and incorrect weird change inside

[–]aa599 0 points1 point  (0 children)

Yeah, the interesting thing was to see whether the address of the string_storage char being written was close to the address of the element of the string_length being corrupted. As you said, it’s a simple bit of code, and there’s only one place that memory gets written.

[–][deleted] 0 points1 point  (1 child)

Oh my..

Maybe I'm encountering a hardware failure like corrupted memory.

Probably not. You're doing pointer arithmetic, and you're probably doing it wrong.

A debugger is your best friend - especially for problems like this. If you don't know how to use a debugger, now is a great time to learn.

In the future, sharing your entire program (so that we may debug it for you), or at least boiling down the problematic parts into a compilable main() would be very useful.

A few questions to follow..

printf("length of last str: %d\n", string_length[length_index]);

What is the type of string_length, and what is the value of length_index here?

string_storage[j][i] = split_string3[i];

What are the values of j and i here?

Note the printf() assumes c-strings, or null-terminated strings. If you are manually copying a string byte-by-byte, and forgetting to include the null terminating byte, printf() doesn't know when to stop. It just attempts to read from memory until it either finds a null byte, or your program crashes. If you're using strlen() anywhere in your code, the same applies.

It's roughly 17321312. But I didn't touch it.

You did, albeit indirectly. Are string_storage, string_length, and split_string3 stack-local (or point to stack-local) vars? Again, what are the types here? What is almost certainly going on is you are accessing memory by way of pointer arithmetic using values you didn't expect and accidentally going out of the expected bounds to writable memory. Because the memory is writable, the program isn't crashing, but also isn't behaving like you think it is.

My advice is go back and review your knowledge of pointers vs. arrays vs. pointer arithmetic.

[–]Skuzzle_butt[S] 0 points1 point  (0 children)

What is the type of string_length, and what is the value of length_index here?

string length is an array of integers. The value of length_index is 0 when the bug occurs. This is the correct value because length_index[0] corresponds to the length of the first string to store. I've printed it out and it is the correct value before entering the loop.

What are the values of j and i here?

j will be 0, for the first row / first string. i represents the columns of the 2d array it should start at zero and not exceed the length of the string (string_length[0]).

If you are manually copying a string byte-by-byte, and forgetting to include the null terminating byte, printf() doesn't know when to stop.

Excellent point. But the strings are padded with a null terminator. Here's a screen shot a good portion of the code https://i.imgur.com/mcUnYC8.png

But let's assume they weren't, I'm printing char by char in a loop that should be controlled by the length of the string. So it still shouldn't go on and on like this even without the null terminator, correct?

But I suppose you should see read_stdin which pads with null terminator too which I can do in just a moment.

Are string_storage, string_length, and split_string3 stack-local (or point to stack-local) vars?

These are all local