memory allocation and dynamic memory allocation - c

i am new in c programming and i just learn about pointer and string,i know when working with pointer and string we must allocate memory for string we want do declared using dynamic memory allocation.I want to calculate length of string without using c function library strlen().but why this below code doesn't give the real length of string,instead when i change *string to string[50] that means i am using array way to calculate,the code works fine and give me the real length of string.
this the code:
#include <stdio.h>
#include <stdlib.h>
int len(char *string);
int main(void){
char *string;
string=(char *)malloc(len(string+1));
puts("enter string:");
fgets(string,sizeof(string),stdin);
printf("length=%d\n",len(string));
return 0;
}
int len(char *string){
int len;
while(*string!='\0'){
string++;
len++;
}
return len-1;
}
this is when i run that code:
enter string:
programming
length=2

Your code describes the chicken and egg problem. To calculate the length, you need a pointer with allocated space & to allocate space you need to calculate the length.
In
string=(char *)malloc(len(string+1));
In malloc(), you are passing string which is a pointer which hasn't yet been initialized or allocated any memory, meaning it contains some garbage value. And then when you calculate its length in len(), it de-references the garbage address it contains, surprisingly you don't get a segfault here.
And then you have not initialized len variable in your len() function, it just adds to the garbage value that len contains and returns.
I ran your code and it gave me a segmentation fault because of the issues mentioned above.

Related

C string struct with mem allocation included

I am working with a bunch of strings for logging. I want to refactor my code and make a new struct that combines the char, its length and allocated size. The idea is to make my internal string operations smoother and the code nicer to read, whilst assigning each string its own max allocated memory to keep the usage to a minimum but prevent stack overflow. I made this simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *str;
int size;
int max;
} Text;
void defText(Text *text, int max)
{
text->str=(char*) malloc(max * sizeof(char));
text->str="";
text->max=max;
}
int main() {
Text *a;
defText(a,50);
a->str="Test all you want";
printf("OUT: %s %zu %lu",a->str,strlen(a->str),sizeof(a->str));
return 0;
}
The function defText initializes and allocates memory. However, when I check the sizeof the char in my struct, I always get 8, no matter what I set in defText. Is this kind of struct handling strings and their properties together even possible? If so, what is wrong here?
There are several problems in your code, this is an example that cleans up these problems:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *str;
// you could use size to keep track of the strlen. That's particularly
// desirable if you find yourself calling strlen "a lot", since that
// function recalculates the length every time it's called
int size;
int max;
} Text;
void defText(Text *text, int max)
{
// no need to cast the return of malloc. In fact, sizeof(char) is defined by
// the standard to be 1 so you could take that out also.
text->str=malloc(max * sizeof(char));
// `=` is not the proper way to write strings in C, you must use strcpy
// or something similar. It looks like here you're simply trying to
// create an empty string.
//text->str="";
// per #JohnBollinger's comment, the best thing to do here to create
// an empty string is simply set to the first byte to the NUL
// terminator.
text->str[0] = '\0';
text->max=max;
}
int main() {
Text a; // store this in automatic memory, now the object exists without having to malloc
defText(&a,50); // Use & to pass the address of a to defText
// as mentioned, this is not the proper way to write data to a string in
// C. What you've done here is create a memory leak and point a.str to
// the string literal "Test all you want". Use strcpy (or similar) to
// write that string into the data you actually malloc'ed (using the dot
// operator now since `a` is no longer a pointer)
//a->str="Test all you want";
strcpy(a.str, "Test all you want");
// a.str is a pointer, and will always be 8 bytes on your system no matter
// the size of the memory it points to
printf("OUT: %s %zu %zu",a.str,strlen(a.str),sizeof(a.str));
// clean up allocated memory. Since we're about to exit, there's
// really no need to do this here (the OS will reclaim all allocated
// memory when the process ends), but if you're writing a more
// involved, long-running program, you need to be sure to handle
// memory allocations and deallocations appropriately as needed
free(a.str);
return 0;
}
Demo
The
a->str
is pointer .
the correct answer is
sizeof(*(a->str))

C dynamic allocated array using memset for initialisation

So i've make a program about an char array that is dinamically allocated, the program is not yet finished but i've got some different return values after i run the program, no warnings, no errors in compiler so i don't know why i get this also sometimes the program crashes..
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main(){
int n,i;
char *tab=NULL;
printf("New size of array: ");
scanf("%d",&n);
tab=(char*)malloc(n*sizeof(char));
memset(tab,'X',n*sizeof(tab));
for(i=0;i<n;i++)
printf("%c",tab[i]);
free(tab);
return 0;
}
In your memset you write n * sizeof(tab), I think you wanted to write :
n * sizeof(char)
You can also add a +1 add the end of your malloc and check the return value, just for security.
The C library function void *memset(void *str, int c, size_t n) copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str.
memset(tab,'X',n*sizeof(char));
You've written n*sizeof(tab), you are copying the character X to unknown memory which might cause crash during runtime.
Look into this line:
memset(tab,'X',n*sizeof(tab));
You declared tab as a pointer, and a storage size of a pointer is more than one byte. Multiplying that by n which is the size of the array you want will cause you to copy data to memory space you're not allowed to access which is why you get a segmentation fault.
If you must use sizeof, then do this:
memset(tab,'X',n*sizeof(char));
or better yet, just do this:
memset(tab,'X',n);
because a char is one byte and n times 1 = n.

puts function gives garbage value in C

I want to copy one string to another string using pointer and I am getting garbage value (some unknown character) from printf function. What is wrong with it?
output is "string for copy**". At the place of ** getting some unknown character.
#include <stdio.h>
#include <conio.h>
void main()
{
char *s="string for copy",*c,*temp;//temp is used to back the
//pointer on 1st position
clrscr();
while(*s!=NULL)
{
*c=*s
c++;
s++;
}
c='\0';
c=temp;//back pointer to first position
printf("String from c:);
puts(c);
getch();
}
You need to allocate memory for your char * variables.
Also you never assign a value to temp (or allocate space for it) but then later in your code you assign c = temp. This means wherever c is currently at in memory will get assigned whatever was in memory at the location of temp.
c is char * are not allocating memory to it. So referring to it - reading from it or writing to it - is undefined behavior.
Allocate appropriate memory for c by using malloc() or other function before you copy characters into it.
So problem is not actually when you try to print using puts() but also when you copy characters to it by *c = *s.
Other than malloc(), change you code as below
...
//allocate memory for c
temp = c;
while(*s!='\0')
{
*c=*s
c++;
s++;
}
*c='\0'; //use *c
c=temp;
...

Segmentation Fault in Simple Offset Encryption

Alright guys, this is my first post here. The most recent assignment in my compsci class has us coding a couple of functions to encode and decode strings based on a simple offset. So far in my encryption function I am trying to convert uppercase alphas in a string to their ASCII equivalent(an int), add the offset(and adjust if the ASCII value goes past 'Z'), cast that int back to a char(the new encrypted char) and put it into a new string. What I have here compiles fine, but it gives a Segmentation Fault (core dumped) error when I run it and input simple uppercase strings. Where am I going wrong here? (NOTE: there are some commented out bits from an attempt at solving the situation that created some odd errors in main)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//#include <stdlib.h>
char *encrypt(char *str, int offset){
int counter;
char medianstr[strlen(str)];
char *returnstr;// = malloc(sizeof(char) * strlen(str));
for(counter = 0; counter < strlen(str); counter++){
if(isalpha(str[counter]) && isupper(str[counter])){//If the character at current index is an alpha and uppercase
int charASCII = (int)str[counter];//Get ASCII value of character
int newASCII;
if(charASCII+offset <= 90 ){//If the offset won't put it outside of the uppercase range
newASCII = charASCII + offset;//Just add the offset for the new value
medianstr[counter] = (char)newASCII;
}else{
newASCII = 64 + ((charASCII + offset) - 90);//If the offset will put it outside the uppercase range, add the remaining starting at 64(right before A)
medianstr[counter] = (char)newASCII;
}
}
}
strcpy(returnstr, medianstr);
return returnstr;
}
/*
char *decrypt(char *str, int offset){
}
*/
int main(){
char *inputstr;
printf("Please enter the string to be encrypted:");
scanf("%s", inputstr);
char *encryptedstr;
encryptedstr = encrypt(inputstr, 5);
printf("%s", encryptedstr);
//free(encryptedstr);
return 0;
}
You use a bunch of pointers, but never allocate any memory to them. That will lead to segment faults.
Actually the strange thing is it seems you know you need to do this as you have the code in place, but you commented it out:
char *returnstr;// = malloc(sizeof(char) * strlen(str));
When you use a pointer you need to "point" it to allocated memory, it can either point to dynamic memory that you request via malloc() or static memory (such as an array that you declared); when you're done with dynamic memory you need to free() it, but again you seem to know this as you commented out a call to free.
Just a malloc() to inputstr and one for returnstr will be enough to get this working.
Without going any further the segmentation fault comes from your use of scanf().
Segmentation fault occurs at scanf() because it tries to write to *inputstr(a block of location inputstr is pointing at); it isn't allocated at this point.
To invoke scanf() you need to feed in a pointer in whose memory address it points to is allocated first.
Naturally, to fix the segmentation fault you want to well, allocate the memory to your char *inputstr.
To dynamically allocate memory of 128 bytes(i.e., the pointer will point to heap):
char *inputstr = (char *) malloc(128);
Or to statically allocate memory of 128 bytes(i.e., the pointer will point to stack):
char inputstr[128];
There is a lot of complexity in the encrypt() function that isn't really necessary. Note that computing the length of the string on each iteration of the loop is a costly process in general. I noted in a comment:
What's with the 90 and 64? Why not use 'A' and 'Z'? And you've commented out the memory allocation for returnstr, so you're copying via an uninitialized pointer and then returning that? Not a recipe for happiness!
The other answers have also pointed out (accurately) that you've not initialized your pointer in main(), so you don't get a chance to dump core in encrypt() because you've already dumped core in main().
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
char *encrypt(char *str, int offset)
{
int len = strlen(str) + 1;
char *returnstr = malloc(len);
if (returnstr == 0)
return 0;
for (int i = 0; i < len; i++)
{
char c = str[i];
if (isupper((unsigned char)c))
{
c += offset;
if (c > 'Z')
c = 'A' + (c - 'Z') - 1;
}
returnstr[i] = c;
}
return returnstr;
}
Long variable names are not always helpful; they make the code harder to read. Note that any character for which isupper() is true also satisfies isalpha(). The cast on the argument to isupper() prevents problems when the char type is signed and you have data where the unsigned char value is in the range 0x80..0xFF (the high bit is set). With the cast, the code will work correctly; without, you can get into trouble.

Taking string input in char pointer

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char *s;
printf("enter the string : ");
scanf("%s", s);
printf("you entered %s\n", s);
return 0;
}
When I provide small inputs of length up to 17 characters (for example "aaaaaaaaaaaaaaaaa") the program works perfectly fine but on providing inputs of larger lengths, it gives me a runtime error saying "main.c has stopped working unexpectedly".
Is there some problem with my compiler (codeblocks) or my pc (windows 7)? Or is it somehow related to the input buffer of C?
It's undefined behaviour as the pointer is uninitialized. There's no problem with your compiler but your code has problem :)
Make s point to valid memory before storing data in there.
To manage buffer overflow, you can specify the length in the format specifier:
scanf("%255s", s); // If s holds a memory of 256 bytes
// '255' should be modified as per the memory allocated.
GNU C supports an non-standard extension with which you don't have to allocate memory as allocation is done if %as is specified but a pointer to pointer should be passed:
#include<stdio.h>
#include<stdlib.h>
int main() {
char *s,*p;
s = malloc(256);
scanf("%255s", s); // Don't read more than 255 chars
printf("%s", s);
// No need to malloc `p` here
scanf("%as", &p); // GNU C library supports this type of allocate and store.
printf("%s", p);
free(s);
free(p);
return 0;
}
the char pointer is not initialized, you should dynamiclly allocate memory to it,
char *s = malloc(sizeof(char) * N);
where N is the maximum string size you can read, And its not safe to use scanf
without specifying the maximum length for the input string, use it like this,
scanf("%Ns",s);
where N same as that for malloc.
You are not allocating any memory to the character array so first try to get memory by calling malloc() or calloc(). then try to use it.
s = malloc(sizeof(char) * YOUR_ARRAY_SIZE);
...do your work...
free(s);
You need to allocate enough memory for buffer where your pointer will point to:
s = malloc(sizeof(char) * BUF_LEN);
and then free this memory if you do not need it anymore:
free(s);
You're not allocating memory for your string, and thus, you're trying to write in a non-authorized memory address. Here
char *s;
You're just declaring a pointer. You're not specifying how much memory to reserve for your string. You can statically declare this like:
char s[100];
which will reserve 100 characters. If you go beyond 100, it will still crash as you mentionned for the same reason again.
The problem is with your code .. you never allocate memory for the char *. Since, there is no memory allocated(with malloc()) big enough to hold the string, this becomes an undefined behavior..
You must allocate memory for s and then use scanf()(I prefer fgets())
#include"stdio.h"
#include"malloc.h"
int main(){
char *str;
str=(char*)malloc(sizeof(char)*30);
printf("\nENTER THE STRING : ");
fgets(str,30,stdin);
printf("\nSTRING IS : %s",str);
return 0;
}
The code in C to read a character pointer
#include<stdio.h>
#include<stdlib.h>
void main()
{
char* str1;//a character pointer is created
str1 = (char*)malloc(sizeof(char)*100);//allocating memory to pointer
scanf("%[^\n]s",str1);//hence the memory is allocated now we can store the characters in allocated memory space
printf("%s",str1);
free(str1);//free the memory allocated to the pointer
}
I was getting this problem. I tried this code below and it worked:
char *text;
scanf("%s", *&text);
I dont know how it worked. I just felt like doing it.

Resources