Access violation when writing location - c

So my code should work this way:
the function gets as input a char**(array of strings) and just char*(string), also int number.
then, I have to realloc the char** to the number, and add to the last pointer in him the string. Here is how I wrote that:
void addReason(char** stringsArr, char* string, int number)
{
stringsArr = (char**)realloc(type, sizeof(char) * number);
*(stringsArr + number - 1) = (char)malloc(sizeof(char) * strlen(string));
strcpy(*(stringsArr + number - 1), string); // the exception thorws here,
//talking about the *(stringsArr + number - 1) pointer
}

First:
stringsArr = (char**)realloc(type, sizeof(char) * number);
should be:
stringsArr = realloc(stringsArr, sizeof(char *) * number);
or even better:
stringsArr = realloc(stringsArr, sizeof(*stringsArr) * number);
Note the parameter to the sizeof operator, and don't cast the return from realloc or malloc.
Second:
*(stringsArr + number - 1) = (char)malloc(sizeof(char) * strlen(string));
should be:
stringsArr[number-1] = malloc(strlen(string) + 1);
sizeof(char) is 1 by definition, so you don't need to specify it. You need to add 1 for the terminating null. Array index notation is generally easier to follow than pointer notation.
Third, on the off-chance that reason actually is a valid identifier and not a copy-paste error:
strcpy(*(stringsArr + number - 1), reason);
should be:
strcpy(stringsArr[number - 1], string);
As additional points:
You should always be checking the return value of malloc and friends.
All identifiers starting with str and a lowercase letter are reserved for the standard library, so your stringsArr and string are technically illegal identifiers.
As noted in the comments, you don't return your new pointer, so you're leaking your new memory here, but since your code clearly doesn't compile anyway, maybe there's more code you're not showing us.

Related

in C, why do I have " "s": initialization requires a brace-enclosed initializer list"?

DISCLAIMER: it's just a piece of the whole algorithm, but since I encountered a lot of errors, I've decided to divide and conquer, therefore, I start with the following code. (goal of the following code: create a string with the remainders of the division by 10 (n%10). for now, it's not reversed, I haven't done it yet, because I wanted to check this code first).
(i'm working in C, in visual studio environment).
I have to implement a function like atoi (that works from a string to a number), but I want to do the opposite (from a number to a string). but I have a problem:
the debugger pointed out that in the lines with the malloc, I should have initialized the string first (initialization requires a brace-enclosed initializer list),
but I have done it, I have initialized the string to a constant (in the 2nd line, I've written "this is the test seed")(because I need to work with a string, so I initialized, and then I malloc it to write the values of (unsigned int n) ).
this is how my program is supposed to work:
(1) the function takes an unsigned int constant (n),
(2) the function creates a "prototype" of the array (the zero-terminated string),
(3) then, I've created a for-loop without a check condition because I added it inside the loop body,
(4) now, the basic idea is that: each step, the loop uses the i to allocate 1 sizeof(char) (so 1 position) to store the i-th remainder of the n/10 division. n takes different values every steps ( n/=10; // so n assumes the value of the division). and if n/10 is equal to zero, that means I have reached the end of the loop because each remainder is in the string). Therefore, I put a break statement, in order to go outside the for-loop.
finally, the function is supposed to return the pointer to the 0-th position of the string.
so, to sum up: my main question is:
why do I have " "s": initialization requires a brace-enclosed initializer list"? (debugger repeated it twice). that's not how string is supposed to be initialized (with curly braces "{}"). String is initialized with " " instead, am I wrong?
char* convert(unsigned int n) {
char s[] = "this is the test seed";
for (unsigned int i = 0; ; i++) {
if (i == 0) {
char s[] = malloc (1 * sizeof(char));
}
if (i != 0) {
char s[] = malloc(i * sizeof(char));
}
if ((n / 10) == 0) {
break;
}
s[i] = n % 10;
n /= 10;
}
return s;
}
char s[]is an array, and therefore needs a brace-enclosed initializer list (or a character string literal). In the C standard, see section 6.7.8 (with 6.7.8.14 being the additional special case of a literal string for an array of character type). char s[] = malloc(...); is neither a brace-enclosed initializer list or a literal string, and the compiler is correctly reporting that as an error.
The reason for this, is that char s[] = ...; declares an array, which means that the compiler needs to know the length of the array at compile-time.
Perhaps you want char *s = malloc(...) instead, since scalars (for example, pointers) can be initialized with an assignment statement (see section 6.7.8.11).
Unrelated to your actual question, the code you've written is flawed, since you're returning the value of a local array (the first s). To avoid memory problems when you're coding, avoid mixing stack-allocated memory, statically allocated strings (eg: literal strings), and malloc-ed memory. If you mix these together, you'll never know what you can or can't do with the memory (for example, you won't be sure if you need to free the memory or not).
A complete working example:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
char *convert(unsigned n) {
// Count digits of n (including edge-case when n=0).
int len = 0;
for (unsigned m=n; len == 0 || m; m /= 10) {
++len;
}
// Allocate and null-terminate the string.
char *s = malloc(len+1);
if (!s) return s;
s[len] = '\0';
// Assign digits to our memory, lowest on the right.
while (len > 0) {
s[--len] = '0' + n % 10;
n /= 10;
}
return s;
}
int main(int argc, char **argv) {
unsigned examples[] = {0, 1, 3, 9, 10, 100, 123, 1000000, 44465656, UINT_MAX};
for (int i = 0; i < sizeof(examples) / sizeof(*examples); ++i) {
char *s = convert(examples[i]);
if (!s) {
return 2;
}
printf("example %d: %u -> %s\n", i, examples[i], s);
free(s);
}
return 0;
}
It can be run like this (note the very useful -fsanitize options, which are invaluable especially if you're beginning programming in C).
$ gcc -fsanitize=address -fsanitize=leak -fsanitize=undefined -o convert -Wall convert.c && ./convert
example 0: 0 -> 0
example 1: 1 -> 1
example 2: 3 -> 3
example 3: 9 -> 9
example 4: 10 -> 10
example 5: 100 -> 100
example 6: 123 -> 123
example 7: 1000000 -> 1000000
example 8: 44465656 -> 44465656
example 9: 4294967295 -> 4294967295

strtol result mismatch while string conversion

After checking out this question I did not found required solution, so I've tried to use strtol in following manner:
in = (unsigned char *)malloc(16);
for(size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i+=2 )
{
long tmp = 0;
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
memcpy(&in[i], &tmp, 1);
}
This code produced several intermediate values:
Can someone please explain me why entire in array gets filled by 0xFF(255) bytes and why tmp is not equal it's estimated value?
Tips about how to improve above code to fill in array with correct hex values also welcome.
Your code is erroneous for multiple counts and the casts hide the problems:
Casting the return value of malloc is not necessary in C and can potentially hide an unsafe conversion if you forget to include <stdlib.h>:
in = (unsigned char *)malloc(16);
Casting the return value of strlen to (size_t) is useless, even redundant as strlen is defined to return a size_t. Again you might have forgotten to include <string.h>...
for (size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i += 2) {
long tmp = 0;
strtol takes a const pointer to char, which argv[2] + i will convert to implicitly. The cast (const char*) is useless. The second argument is the address of a char*. You pass the address of the fifth element of argv, in other terms &argv[4], most certainly not what you indent to do, although your loop's purpose is quite obscure...
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
Copying the long value in tmp with memcpy would require to copy sizeof(tmp) bytes. Copying the first byte only has an implementation defined effect, depending on the size of char and the endianness of the target system:
memcpy(&in[i], &tmp, 1);
}
You should post a complete compilable example that illustrates your problem, a code fragment is missing important context information, such as what header files are included, how variables are defined and what code is executed before the fragment.
As written, your code does not make much sense, trying to interpret its behavior is pointless.
Regarding the question in reference, your code does not even remotely provide a solution for converting a string of hexadecimal characters to an array of bytes.

Coverity deflect: - String length miscalculation (BAD_ALLOC_STRLEN)

I have a coverity deflect to be fixed but I am not sure about it. I have a function (void my_function(a_type *my_variable)) with the following problematic line of code:
body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[1]) +1);
where body is an unsigned char*.
The Coverity message:
String length miscalculation (BAD_ALLOC_STRLEN)
Using "strlen(((my_type *)*my_variable)->Param2.body + 1)"
instead of "strlen(((my_type *)*my_variable)->Param2.body) + 1"
as an argument to "malloc" might be an under-allocation.
Now, given the strlen function call, which looks like this:
strlen(&((my_type*) *my_variable)->Param2.body[1])
and this line is identical to:
strlen(&((my_type*) *my_variable)->Param2.body + 1)
So this should be changed according to the message, and the result would be:
body = malloc((strlen(&((my_type*) *my_variable)->Param2.body)+1) +1);
Why is bad such an argument for malloc? I do not see what is the actual problem here so I am unsure about this solution and/or its necessity.
Additional information is that, &((my_type*) *my_variable)->Param2.body[1] (simply &Param2.body[1]) will be copied into body using strcpy, like:
strcpy(body, &((my_type *) *my_variable)->Param2.body[1]);
No, ...body[1] and ...body + 1 are not identical. The first has a type that is the element type of the body array, the second has type ptr-to-element-type. Read your C book again :-)
Coverity tries to tell you that you make the same error as in
char foo[42];
/* write a string to foo */
bar = malloc (strlen(foo + 1)); /* which is strlen(&foo[1]) */
when the correct code is
bar = malloc (strlen(foo) + 1);
I think you misunderstood the paranthesis.
The + 1 in the coverity suggestion is outside the strlen(...)
I think coverity gets worried because you want to take strlen from index 1 instead of index 0. Coverity would expect index 0 as starting point - like:
body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[0]) +1);
^
which is also
body = malloc(strlen(((my_type*) *my_variable)->Param2.body) +1);
^ ^
No & operator No [0]
as suggested by coverity
I have reached that conclusion #rici was correct. Considering the following simulation:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Param2{
char* body;
}Param2;
int main()
{
Param2 test;
test.body = "test_string\0";
printf("%s, size: %d + 1 terminating null\n\n",test.body, strlen(test.body));
printf("original: %d \n", (strlen(&test.body[1]) + 1));
printf("what coverity thinks: %d \n", strlen(test.body + 1));
printf("what coverity suggests: %d \n", (strlen(test.body) + 1));
printf("a more transparent way: %d \n\n", (strlen(test.body + 1) + 1));
return 1;
}
This is the output:
There are three cases (4th is the same as 1st). The allocated memory can be seen on the image above for all cases. Now, if we want to copy the source string from the 2. byte (&body[1]), that would mean 10 bytes of data in the example. And according to the strcpy documentation:
To avoid overflows, the size of the array pointed by destination shall
be long enough to contain the same C string as source (including the
terminating null character), and should not overlap in memory with
source.
We need one more for the null termination giving us 11 bytes to be allocated. Coverity believes that we are allocating 10 bytes, and suggest to allocate 12.
But as we can see, the original code allocates 11 bytes which is the exact number of bytes we need here, making the coverity deflect false positive.

Reallocing a char*

I am trying to do a function that will store in a char array some information to print on it:
int offset = 0;
size_t size = 1;
char *data = NULL;
data = malloc(sizeof(char));
void create(t_var *var){
size_t sizeLine = sizeof(char)*(strlen(var->nombre)+2)+sizeof(int);
size = size + sizeLine;
realloc(data, size);
sprintf(data+offset,"%s=%d\n",var->name,var->value);
offset=strlen(data);
}
list_iterate(aList, (void *)create);
t_var is a struct that has two fields: name (char*) and value (int).
What's wrong with this code? When running it on Valgrind it complains about the realloc and sprintf.
Without knowing the specific valgrind errors, the standout one is:
realloc(data, size); should be data = realloc(data, size);
I'm sorry to say that, but almost EVERYTHING is wrong with your code.
First, incomplete code.
You say your t_var type has two members, name and value.
But your code refers to a nombre member. Did you forget to mention it or did you forget to rename it when publishing the code?
Second, misused sizeof.
You use a sizeof(int) expression. Are you aware what you actually do here?!
Apparently you try to calculate the length of printed int value. Alas, operator sizeof retrieves the information about a number of bytes the argument occupies in memory. So, for example, for 32-bits integer the result of sizeof(int) is 4 (32 bits fit in 4 bytes), but the maximum signed 32-bit integer value is power(2,31)-1, that is 2147483647 in decimal. TEN digits, not four.
You can use (int)(2.41 * sizeof(any_unsigned_int_type)+1) to determine a number of characters you may need to print the value of any_unsigned_int_type. Add one for a preceding minus in a case of signed integer types.
The magic constant 2.41 is a decimal logarithm of 256 (rounded up at the 3-rd decimal digi), thus it scales the length in bytes to a length in decimal digits.
If you prefer to avoid floating-point operations you may use another approximation 29/12=2.41666..., and compute (sizeof(any_unsigned_int_type)*29/12+1).
Third, sizeof(char).
You multiply the result of strlen by sizeof(char).
Not an error, actually, but completely useless, as sizeof(char) equals 1 by definition.
Fourth, realloc.
As others already explained, you must store the return value:
data = realloc(data, size);
Otherwise you risk you loose your re-allocated data AND you continue writing at the previous location, which may result in overwriting (so destroying) some other data on the heap.
Fifth, offset.
You use that value to determine the position to sprintf() at. However, after the print you substitute offset with a length of last printout instead of incrementing it. As a result consecutive sprintfs will overwrite previous output!
Do:
offset += strlen(data);
Sixth: strlen of sprintf.
You needn't call strlen here at all, as all functions of printf family return the number of characters printed. You can just use that:
int outputlen = sprintf(data+offset, "%s=%d\n", var->name, var->value);
offset += outputlen;
Seventh: realloc. Seriously.
This is quite costly function. It may need to do internal malloc for a new size of data, copy your data into a new place and free the old block. Why do you force it? What impact will it have on your program if it needs to print five thousand strings some day...?
It is also quite dangerous. Really. Suppose you need to print 5,000 strings but there is room for 2,000 only. You will get a NULL pointer from realloc(). All the data printed to the point are still at the current data pointer, but what will you do next?
How can you tell list_iterate to stop iterating...?
How can you inform the routine above the list_iterate that the string is incomplete...?
There is no good answer. Luckily you needn't solve the problem — you can just avoid making it!
Solution.
Traverse your list first and calculate the size of buffer you need. Then allocate the buffer — just once! — and go on with filling it. There is just one place where the allocation may fail and you can simply not go into the problem if that ever happens:
int totaloutputlength = 0;
char *outputbuffer = NULL;
char *currentposition = NULL;
void add_var_length(t_var *var){
const int numberlength = sizeof(var->value)*29/12 + 1;
totaloutputlength += strlen(var->name) + 2 + numberlength;
}
void calculate_all_vars_length(t_list *aList){
totaloutputlength = 0;
list_iterate(aList, (void *)add_var_length);
}
void sprint_var_value(t_var *var){
int outputlen = sprintf(currentposition, "%s=%d\n", var->name, var->value);
currentposition += outputlen; // advance the printing position
}
int sprint_all_vars(t_list *aList){
calculate_all_vars_length(aList);
outputbuffer = malloc(totaloutputlength + 1); // +1 for terminating NUL char
// did allocation succeed?
if(outputbuffer == NULL) { // NO
// possibly print some error message...
// possibly terminate the program...
// or just return -1 to inform a caller something went wrong
return -1;
}
else { // YES
// set the initial printing position
currentposition = outputbuffer;
// go print all variables into the buffer
list_iterate(aList, (void *)sprint_var_value);
// return a 'success' status
return 0;
}
}

Memory loss in following code when the CPU is 32 bit processor

I have a function to convert integer to string .The function is
char * Int_String(int Number)
{
char* result;
NAT size = 1;
if (Number > 9) {
size = (NAT)log10((double) Number) + 1;
} else if (Number < 0) {
size = (NAT)log10((double) abs(Number)) + 2; /* including '-' */
}
size++; /* for '\0' */
result = (char *) memory_Malloc(sizeof(char) * size);
sprintf(result, "%d", Number);
return result;
}
NAT is typedef unsigned int
Number is int
I am using this function in the following manner
char *s2;
char **Connections;
Connections = memory_Malloc(nc*sizeof(char*));
char con[]="c_";
k1=1;
for (i=0; i<nc ; i++){
s2 = Int_ToString(k1);
Connections[i]= string_Conc(con,s2);
string_StringFree(s2);
k1= k1+1;
}
And the functionschar* string_Conc(const char *s1, const char *S2) is
{
char* dst;
dst = memory_Malloc(strlen(s1) + strlen(s2) + 1);
strcpy(dst, s1);
return strcat(dst,s2);
}
I am using following methods to free its memory:
for(i=0; i<nc; i++){
memory_Free(Connections[i],sizeof(char));
}
memory_Free(Connections,nc*sizeof(char*));
The problem that i am getting is: i can free all the allocated memory when nc<=9.But when it is >=10 leakes memory in the multiple of 4 bytes with each increase in number. How can I remove the problem.Any help will be appreciated.
EDIT
void memory_Free(POINTER Freepointer, unsigned int Size)
Thanks,
thetna
You don't show the implementation of memory_Free (neither memory_Malloc), so we don't know why you need to pass the supposed size of the memory block to be freed as a 2nd parameter (the standard free() doesn't need this). However, here
memory_Free(Connections[i],sizeof(char));
it is certainly wrong: sizeof(char) is 1 on most platforms, but the size of the allocated block is at least 4 bytes for each string in the array (as the strings contain "c_" plus at least one digit plus the terminating '\0').
Update
Looking through the source code you linked, this indeed seems to be the cause of your problem! The code inside memory_Free seems to align memory block sizes - I can assume that to 4-byte boundaries, which is very common. In this case, if the passed Size is 1, it happens to be corrected to 4 - exactly the right value in case of single digit numbers as shown above! However, numbers greater than 9 are converted to (at least) two digits, thus the size of the converted string is already 5. A block of 5 bytes is most probably allocated as an aligned block of 8 bytes under the hood - but since memory_Free is always called with a Size of 1, it always frees only 4 bytes. This leaves 4 bytes leaking per each number above 9, precisely as you described in your comment above!
To fix this, you need to modify the line above to
memory_Free(Connections[i], strlen(Connections[i]) + 1);

Resources