I'm trying to understand malloc but I keep getting "Segmentation fault: 11" with this piece of code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0, j = 0;
char ** ptr = (char **) malloc(sizeof(char*));
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
printf("%s\n", ptr[i]);
}
return 0;
}
I thought there wasn't enough bytes being allocated so I did malloc(sizeof(char*) * 100, but gives me the same error. What am I not understanding here?
When you allocate a 2D array, you need to allocate the individual sub-arrays as well. In addition, you need to say how many elements you wish to have. For that you multiply the desired count by the number of elements, like this:
char ** ptr = (char **) malloc(5*sizeof(char*));
// Size=5 ---------------------^
for(int i = 0; i < 5; i++) {
ptr[i] = malloc(11*sizeof(char));
// sizeof(char) is always 1, so the multiplication above is redundant.
// You need 11 elements for ten characters
for(int j = 0; j < 10; j++) {
ptr[i][j] = 'a';
}
// don't forget to null-terminate the string:
ptr[i][10] = '\0';
printf("%s\n", ptr[i]);
}
Your code is totally messed up in every aspect!
1) you allocated memory for exactly 1 Pointer to it. This means you can access ptr[0], but not ptr[1] ... ptr[4] as you are trying to do.
2) you never allocate anything for the elements in ptr[i].
3) you try to print a string a ptr[i] which is (even if your allocation would be right) never terminated.
4) although this is obviously only a beginners test, never forget to free your memory!!!!
To reach something CLOSE to what your sampel code is describing you could do:
int main()
{
int i,j;
char ** ptr = malloc( 5 * sizeof(char*) ); /* an array of 5 elements of type char* */
for(i = 0; i < 5; i++)
{
ptr[i] = malloc( 11*sizeof(char) ); /* The element i of the array is an array of 11 chars (10 for the 'a' character, one for the null-termination */
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = '\0'; /* strings need to be null terminated */
printf("%s\n", ptr[i]);
}
// free your memory!
for (i=0; i<5; i++ )
{
free(ptr[i]);
}
free(ptr);
return 0;
Another way to allocate the memory is:
char (*ptr)[11] = malloc( sizeof(char[5][11]) );
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = 0;
printf("%s\n", ptr[i]);
}
free(ptr);
It seems less hassle to use a single allocation than to use a lot of allocations, unless you have a pressing reason to do the latter.
Related
I wanted to copy the first half of my dynamic array into the second half of the same array, but the output here is from ptr[100] to ptr[200] 9.90. I think I coded everything fine but I dont know where the problme is. Can you help me?
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int i;
int j;
double * ptr = calloc(100, sizeof(double));
if (ptr == NULL)
return 0;
for(i = 0; i < 100; i++) {
ptr [i] = i / 10.0;
}
for(i = 0; i < 100; i++) {
printf("ptr[%d] = %.2f\n", i, ptr[i]);
}
if (realloc(ptr, 200) == NULL)
return 0;
for (i = 0; i < 100; i++)
for (j = 100; j < 201; j++)
ptr [j] = ptr[i];
for (j = 100; j < 201; j++)
printf("ptr[%d] = %.2f\n", j, ptr[j]);
return 0;
}
You are underallocating on the realloc. You didn't make enough space for 200 doubles, so attempting to access ptr[x] is undefined behavior for values of x > 99. Also, realloc may move the memory, so you need to assign the new value back to ptr. For example:
ptr = realloc(ptr, 200 * sizeof *ptr);
if( ptr == NULL ){
perror("realloc");
exit(1);
}
And after this, accessing ptr[200] is undefined behavior. You need to reduce the scope of the loop index to for( j = 100; j < 200; j++ )
You are overwriting for every copy
for (i = 0; i < 100; i++) // for every item in the first half
for (j = 100; j < 201; j++) // into every cell
ptr [j] = ptr[i];
shoud be
for (i = 0; i < 100; i++)
ptr [i+100] = ptr[i];
and issue 2:
you didn't raallocate enough memory : change realloc(ptr, 200) to realloc(ptr, 200 * sizeof(double))
I learnt about the concept of array of pointers and ragged arrays, but i'm not able to understand why my code isn't working.
#include<stdio.h>
int main(void)
{
int* b[10] ;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
scanf_s("%d", (*(b+i)+j));
}
}
return 0;
}
There are multiple issues with your code, so I will just post the corrected one with explanations:
int *b[10];
for (int i = 0; i < 3; i++) {
// you need to allocate memory to each pointer inside your array as well
// I have allocated for 3, since you scan 3 integers
b[i] = malloc(3 * sizeof(int));
for (int j = 0; j < 3; j++) {
// use scanf like this, you need the address not the value of variable you are scanning
scanf("%d", (*(b + i) + j));
}
}
You need to include the header file for malloc.
#include <stdlib.h>
Also, don't forget to free the dynamically allocated memory later to avoid memory leaks.
You are declaring an array of pointers:
int* b[10];
you need to allocate memory for each of those pointers, namely:
for (int i = 0; i < 10; i++) {
b[i] = malloc(3 * sizeof(int));
}
From Difference between scanf and scanf_s one can read:
scanf originally just reads whatever console input you type and assign
it to a type of variable.
(..)
scanf_s has an argument(parameter) where you can specify the buffer size and actually control the limit of the input so you don't crash the whole building.
Therefore, what you need is scanf, hence change your code from:
scanf_s("%d", (*(b+i)+j));
to
scanf("%d", (*(b+i)+j));
You should also check the returning value of the scanf function, and free the memory of the dynamically allocated array.
An example of a full running code:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int array_size = 3;
int* b[array_size] ;
// Allocate memory for my array
for (int i = 0; i < array_size; i++)
b[i] = malloc(3 * sizeof(int));
int scanf_value = 0;
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++){
if(scanf("%d", &b[i][j]) != 1){
while(getchar()!='\n'); // clean the input buffer
printf("Invalid Input! Add just numbers\n");
j--;
}
}
// print those elements
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++)
printf("%d ",b[i][j]);
// lets free the memory
for (int i = 0; i < array_size; i++)
free(b[i]);
return 0;
}
scanf_s takes an address of a variable but you are passing a value. Doesn't your compiler complain? If not, bump up the warning/errors levels. Others already told you that you need to allocate memory for the array pointers to point at. If this was production code remember to free().
There is a pointer array in the following code (char * newName) which is giving me some trouble. I believe the issue is somewhere between the backslashes i used to create barriers below. I have attached a picture below. All of the output is working correctly, however, there are 3 outputs of strings right under the word "santiago" that all begin with a strange unicode character and I am stumped as to why that is happening. The letters that come after the strange character (tbuq, bwi, etc) are all correct as well, so I just need to get rid of that character. I would greatly appreciate some guidance here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int compare(const void* a, const void* b)
{
return strcmp(*(const char**)a, *(const char**)b);
}
void sort(char* names[], int n)
{
qsort(names, n, sizeof(char*), compare);
}
int main()
{
int i, j, k, n;
char alphabet[26];
for(i = 0; i < 26; i++)
{
alphabet[i] = i + 97;
}
char newAlphabet[26];
printf("input the new alphabet\n");
for(i = 0; i < 26; i++)
{
scanf(" %c", &newAlphabet[i]);
}
printf("How many names will you input?");
scanf(" %d", &n);
char * names[n];
printf("Enter the names: \n"); //erase before submitting
//the user will now enter the names one by one
for (i = 0; i < n; i++)
{
names[i] = (char *) malloc(100 * sizeof(char)); //allocating memory of 100 for each name pointer
if (names[i] == 0)
{
printf("Error.");
exit(1);
}
scanf("%s", names[i]);
}
for(i = 0; i < n; i++)
{
printf("%s\n", names[i]);
}
int nameConvert[n][100];
//convert the strings of names to their corresponding indexes based on the a = 0, b = 1, etc
for(k = 0; k < n; k++)
{
for(i = 0; i < (strlen(names[k])); i++)
{
for(j = 0; j < 26; j++)
{
if((*(names[k] + i)) == alphabet[j])
{
nameConvert[k][i] = j;
break;
}
}
}
}
////////////////////////////////////////////////////////////////////////////
char * newName[n];
for(i = 0; i < n; i++)
{
newName[i] = '\0';
}
for (k = 0; k < n; k++)
{
newName[k] = (char* ) malloc(100 * sizeof(char));
for(i = 0; i < (strlen(names[k])); i++)
{
char tempstr[2];
tempstr[0] = newAlphabet[nameConvert[k][i]];
tempstr[1] = '\0';
strcat(newName[k], tempstr);
}
printf("%s\n", newName[k]);
}
/////////////////////////////////////////////////////////////////////////////
for(i=0; i < n; i++)
{
for(j = 0; j < strlen(names[i]); j++)
{
printf("%d ", nameConvert[i][j]);
}
printf("\n");
}
sort(newName, n);
for(i = 0; i < n; i++)
{
printf("%s\n", names[i]);
}
return 0;
}
Since you are using strcat(), you have to ensure that the memory is zero (NULL) initialized, since we are talking about strings, of course. You can do it like this:
newName[k] = malloc(100 * sizeof(char));
newName[k][0] = '\0';
That way, you basically NULL-terminate the string in the first character, which means that you have an empty string. Then, you append your actual data to that string.
Without that step, you had a C string that was not NULL-terminated, something that the C string standard library needs in order to operate and know where the string ends.
Or follow #LinusGudmundsson suggestion (more expensive, since it will iterate over the 100 elements in order to initialize them all), and replace that malloc call with this:
newName[k] = calloc(100 , sizeof(char));
where the call to that method zero initializes the memory for you too. Read more in Difference between malloc and calloc?
The output you should get now (with either approach):
input the new alphabet
b j k v q z c d e t u h w x n o p f g l y m r s i a
How many names will you input?3
Enter the names:
jake amy santiago
jake
amy
santiago
tbuq
bwi
gbxlebcn
9 0 10 4
0 12 24
18 0 13 19 8 0 6 14
jake
amy
santiago
PS: Not the cause of the problem, but Do I cast the result of malloc? No.
in my code i use malloc to create n string for my project
and after that , i created 'tr' to put all of string from
**str with small letters .
and it give me an error :
Run-Time Check Failure #3 - The variable 'str' is being used without being initialized.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(void)
{
int n;
char **str;
char *tr;
int cnt, k;
cnt = k = NULL;
printf("Enter number fo strings:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n);
str = (char**)malloc(sizeof(char)*n + 1);
puts("Enter The strings");
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
scanf("%s", &str[i][j]);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (str[i][j] >= 'a' && str[i][j] <= 'z')
cnt++;
}
}
tr = (char*)malloc(sizeof(char)*(cnt + 1));
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (str[i][j] >= 'a' && str[i][j] <= 'z')
tr[k++] = str[i][j];
}
}
tr[k] = NULL;
puts(tr);
free(tr);
free(str);
}
char **str;
char *tr;
int cnt, k;
cnt = k = NULL;
printf("Enter number fo strings:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n); // here
you use str which is uninitialized. What do you expect? str has indeterminate value since it is uninitialized and almost certainly holds an invalid pointer value. Dereferencing an invalid pointer (which the operator [] does) is undefined behaviour.
What you'd have to do is first allocating memory for str to hold the pointers to the strings.
Btw.
puts("Enter The strings");
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
scanf("%s", &str[i][j]);
}
Is also incorrect. There is no need for the inner loop to read input from stdin and store it in str[i]. Also, don't use %s without specifying a with to limit the number of characters written to the destination.
if (str[i][j] >= 'a' && str[i][j] <= 'z')
That's what islower() from <ctype> is for.
free(str);
That's not enough to deallocate the memory since str points to a number of pointers to char which also point to allocated memory.
for (size_t i = 0; i < n; ++i)
free(str[i]);
free(str);
to the rescue.
You're not allocating before using, you're using then allocating, but also allocating incorrectly. The correct allocation is:
str = malloc(sizeof(char*) * n);
Where str is an array of char*, not an array of char.
It's good that you're listening to your compiler warnings, but this one was really specific and you should be able to find the problem. Ordering of allocations is extremely important and "close enough" is not acceptable. It either works, or it's undefined behaviour.
You have these two sections of code in the wrong order:
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n);
str = (char**)malloc(sizeof(char)*n + 1);
You need to allocate memory for str before you can assign to str[i]. And it should be sizeof(char *) * n; there's no need to add 1 to this (you only need this in tr, since you add a null terminator at the end).
It should be:
str = malloc(sizeof(char*)*n);
for (int i = 0; i < n; i++) {
str[i] = malloc(sizeof(char)*n);
}
After
Also, please read Do I cast the result of malloc? and Why is it considered a bad practice to omit curly braces?
gcc 4.6.2 c89
Allocating memory for a 2D array and filling with characters.
However, I don't seem to be filling as when I print nothing is displayed.
Am I doing something wrong here?
char **attributes = NULL;
/* TODO: Check for memory being allocated */
attributes = malloc(3 * sizeof(char*));
int i = 0;
int k = 0;
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
printf("attributes[i][k] [ %c ]\n", attributes[i][k]);
}
}
Many thanks for any advice,
Two major issues:
First Issue:
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
You are reallocating sdp_attributes[i] at each iteration of the inner loop - thereby overwriting it each time. You probably wanted this instead:
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
Second Issue:
sdp_attributes[i][k] = k;
You are basically writing the lower ascii characters. Most of them are not printable.
Something like this might do what you want:
sdp_attributes[i][k] = k + '0';
You probably want:
for (i = 0; i < 3; i++)
{
attributes[i] = malloc(5 * sizeof(char));
for (k = 0; k < 5; k++)
{
attributes[i][k] = k;
}
}
This ignores error checking on the allocation.
It also fixes the name of the array to match the declaration, but your code either wasn't compiling (don't post non-compiling code unless your question is about why it doesn't compile!) or you have another variable called sdp_attributes declared somewhere which you weren't showing us.
Your code was leaking a lot of memory. Each time around the k-loop, you allocated a new array of 5 characters and stored the pointer in attributes[i] (or sdp_attributes[i]), storing the new pointer over what was there before, so you overwrote the value of the first 4 pointers. You could not possibly free the first four items - they were lost irretrievably. Also, on the last iteration, you initialized the 5th element of the final array, but the previous 4 were not initialized and therefore contained indeterminate garbage.
Also, in your printing loop, the values in the array are control characters ^#, ^A, ^B, ^C and ^D; these do not necessarily print well with %c (especially not ^#, which is also known as NUL or '\0'). The printf() statement might be better written as:
printf("attributes[%d][%d] [ %d ]\n", i, k, attributes[i][k]);
This prints the array indexes (rather than simply the characters [i][k] for each entry), and prints the control characters as integers (since the char values are promoted to int when passed to printf()) rather than as control characters.
(It's also more conventional to use i and j for a pair of nested loops, and i, j, and k for triply nested loops, etc. However, that's a very minor issue.)
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
Your erasing the allocated memory every time you loop in the inner most loop.
Here is a correct version.
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
sdp_attributes[i][k] = k;
}
}
And you should fix your declaration:
attributes = malloc(3 * sizeof(char*));
to
sdp_attributes = malloc(3 * sizeof(char*));
Don't forget to free up all the memory allocated
for(i = 0; i < 3; i++)
{
free(sdp_attributes[i]);
}
free(sdp_attributes);
The correct way to allocate and assign elements to 2d array is as follows (but this is a int array, you can try and change it for char array):
One thing to note: As mentioned by #Mysticial, you should add/subtract '0' to your int value to get the char value when using ASCII character set (remember our itoa() functions!).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
for (i=0 ; i<row ; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Few points to note:
error handling should be added for malloc()
malloc()'ed memory must be free()'ed