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;
}
}
Related
I'm having trouble with the following: I want to take a large number (cca. 15-digit) and turn it into individual digits and store them in an array. I will need these digits further on in the code. The problem is, if I declare the array outside the while loop, it stores the first four values, but then I get a segmentation fault. If I declare it within the loop, the code works as I want it to, but then I don't know how to move the array out of that loop, so that I could use it further. How can I solve this? This is what I've compiled:
unsigned long long card_num;
printf("Enter your credit card number:\n");
scanf("%llu", &card_num);
int count = 0;
while (card_num != 0)
{
int digits[count]; //declaring array into which digits will be stored
digits[count] = card_num%10; // get last digit, store it in array
card_num = card_num/10; //remove last digit
printf("Digit[%i] = %i\n", count, digits[count]);
printf("Number of digits: %i\n", count);
count ++;
}
In your code, for the very first iteration
int digits[count];
count is 0, which violates the constraints mentioned in spec. As per C11, chapter 6.7.5.2,
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. [....]
and
If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero
So, this is not a valid code.
As already mentioned, what you are doing is plain wrong.
There is several ways to solve this issue. The easiest would be to allocate an array at the beginning of your program with enough space for all your usecases with something like :
#define MAX_DIGIT 50
int digits[MAX_DIGIT];
Then you just have to check you are not going over this array by checking that count < MAX_DIGIT.
Another way would be using dynamic memory allocation using an int pointer int *digits and malloc (I let you google that) once you know the size of the array you'll need. You'll have to change a bit your code to know the number of digits before starting to get the digits as you need to allocate the memory before starting to store digits.
You could use realloc to keep a code similar to what you already have, but I wouldn't advise it as it is not efficient to realloc memory for each value that you add.
Your logic is fine.
What went wrong is that you tried to increase the length of a fixed-length array while iterating which is not allowed.
You should never change the length of a fixed-length array anywhere in the program.
However if you want to change the length of an array during runtime you must use the malloc and realloc functions to do so.
Check out this example:
//declarations
int *storeNum;
storeNum = (int *)malloc(1 * sizeof(int));
//logic
while(num != 0) {
if(i > 0)
storeNum = realloc(storeNum, (i+1) * sizeof(int));
storeNum[i] = num % 10;
num = num/10;
++i;
}
Here first I declared the array size initially as one and later incremented it using realloc function.
You also have the array size stored in i which you can use later in your code in loops.
But keep in mind that the digits will be stored in your array in reverse order.
Also, you shouldn't declare an array within a loop.
Since you have "declared" the array, each time the compiler enters the loop while iterating it will consider the array-declaration as a new array. That is all.
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.
I'm experiencing some troubles with my code written in C. It's all about an int * vector intially declared and dynamically allocated but when it comes to filling it with data it stuck on the first element and won't increment the counter to fill the rest of the vector
my header file : instance.h
struct pbCoupe
{
int tailleBarre;
int nbTaillesDem;
int nbTotPcs;
int * taille;
int * nbDem;
};
my code : coupe.c
pb->taille = (int*) malloc (pb->nbTaillesDem * sizeof(int));
pb->nbDem = (int*) malloc (pb->nbTaillesDem * sizeof(int));
while (i < pb->nbTaillesDem)
{
fscanf_s(instanceFile,"%s",data,sizeof(data));
pb->taille[i] = atoi(data); //<-- here is the problem !! it only accept the first value and ignore all the rest
printf("%s\n",data);
fscanf_s(instanceFile,"%s",data,sizeof(data));
pb->nbDem[i] = atoi(data); //<-- the same problem here too !!
printf("%s\n",data);
i++;
}
Your interpretation of sizeof is wrong, since data is the buffer that the string is being parsed into.
It returns the size of the the variable, not the size of the the what the variable (or namely a pointer) points to
Strings in C are all pointer to the size would be 4 bytes on a 32-bit system, 8 on a 64-bit.
Since it prints all the number it reading more numbers that intended with each loop iteration 4 bytes = 4 characters, atoi on parses the first integer and returns,
EDIT: If it is a buffer array, sizeof returns the size of the array.
You need to make sure you are only reading in a single number per iteration of the loop to solve this issue.
If you don't care for the literal string, best thing you can do is use:
fscanf(instanceFile, "%d", ((pb->taille) + i)));
//and store the integer into the index right away
//last param same as &pb->taille[i]
I have a toy cipher program which is encountering a bus error when given a very long key (I'm using 961168601842738797 to reproduce it), which perplexes me. When I commented out sections to isolate the error, I found it was being caused by this innocent-looking for loop in my Sieve of Eratosthenes.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
// CANDIDATE_PRIMES is a macro which sets the length of the array to
// two less than the upper bound of the sieve. (2 being the first prime
// and the lower bound.)
for (i=0;i<CANDIDATE_PRIMES;i++)
{
printf("i: %d\n", i); // does not print; bus error occurs first
//candidatePrimes[i] = PRIME;
}
At times this has been a segmentation fault rather than a bus error.
Can anyone help me to understand what is happening and how I can fix it/avoid it in the future?
Thanks in advance!
PS
The full code is available here:
http://pastebin.com/GNEsg8eb
I would say your VLA is too large for your stack, leading to undefined behaviour.
Better to allocate the array dynamically:
int *candidatePrimes = malloc(CANDIDATE_PRIMES * sizeof(int));
And don't forget to free before returning.
If this is Eratosthenes Sieve, then the array is really just flags. It's wasteful to use int if it's just going to hold 0 or 1. At least use char (for speed), or condense to a bit array (for minimal storage).
The problem is that you're blowing the stack away.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
If CANDIDATE_PRIMES is large, this alters the stack pointer by a massive amount. But it doesn't touch the memory, it just adjusts the stack pointer by a very large amount.
for (i=0;i<CANDIDATE_PRIMES;i++)
{
This adjusts "i" which is way back in the good area of the stack, and sets it to zero. Checks that it's < CANDIDATE_PRIMES, which it is, and so performs the first iteration.
printf("i: %d\n", i); // does not print; bus error occurs first
This attempts to put the parameters for "printf" onto the bottom of the stack. BOOM. Invalid memory location.
What value does CANDIDATE_PRIMES have?
And, do you actually want to store all the primes you're testing or only those that pass? What is the purpose of storing the values 0 thru CANDIDATE_PRIMES sequentially in an array???
If what you just wanted to store the primes, you should use a dynamic allocation and grow it as needed.
size_t g_numSlots = 0;
size_t g_numPrimes = 0;
unsigned long* g_primes = NULL;
void addPrime(unsigned long prime) {
unsigned long* newPrimes;
if (g_numPrimes >= g_numSlots) {
g_numSlots += 256;
newPrimes = realloc(g_primes, g_numSlots * sizeof(unsigned long));
if (newPrimes == NULL) {
die(gracefully);
}
g_primes = newPrimes;
}
g_primes[g_numPrimes++] = prime;
}
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);