After Segfault: Is there a way, to check if pointer is still valid?
Of course if the stack or other memory that you rely upon has been corrupted then there could be problems, but that is true for any code.
Assuming that that there is no problem with the stack or other memory that you rely upon, and assuming that you do not call any functions like malloc()
that are not async-signal safe, and assuming that you do not attempt to return from your signal handler, then there should be no problem reading or writing your buffer from within your signal handler.
If you are trying to test whether a particular address is valid, you could use a system call such as mincore()
and check for an error result.
Checking if pointer is NULL gives segmentation fault
you do
while(traverse->next!=NULL && alternate->next!=NULL)
traverse->next = alternate->next;
traverse = traverse->next;
alternate = traverse->next;
if((alternate->next)==NULL) //presence of this if statement causes segmentation fault
so in fact
while(traverse->next!=NULL && alternate->next!=NULL)
traverse = alternate->next;
alternate = traverse->next;
if((alternate->next)==NULL) //presence of this if statement causes segmentation fault
so in fact
while(traverse->next!=NULL && alternate->next!=NULL)
alternate = alternate->next->next;
if((alternate->next)==NULL) //presence of this if statement causes segmentation fault
so in fact
while(traverse->next!=NULL && alternate->next!=NULL)
if((alternate->next->next->next)==NULL) //presence of this if statement causes segmentation fault
when alternate->next->next
is NULL (not checked by the while) alternate->next->next->next
causes your segmentation fault
A solution is :
void deleteAlt(struct Node * head)
{
if (head != NULL) {
while (head->next != NULL) {
Node * d = head->next;
head->next = head->next->next;
free(d);
head = head->next;
}
}
}
A complete program to prove :
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int v;
struct Node * next;
} Node;
Node * make(int v, Node * n)
{
Node * r = malloc(sizeof(Node));
r->v = v;
r->next = n;
return r;
}
void pr(Node * l)
{
while (l != NULL) {
printf("%d ", l->v);
l = l->next;
}
putchar('\n');
}
void deleteAlt(struct Node * head)
{
if (head != NULL) {
while (head->next != NULL) {
Node * d = head->next;
head->next = head->next->next;
free(d);
head = head->next;
}
}
}
int main()
{
Node * l = make(1, make(2, make(3, make(4, make(5, NULL)))));
pr(l);
deleteAlt(l);
pr(l);
/* free rest of list */
while (l != NULL) {
Node * n = l->next;
free(l);
l = n;
}
}
Compilation and execution:
pi@raspberrypi:/tmp $ gcc -pedantc -Wextra l.c
pi@raspberrypi:/tmp $ ./a.out
1 2 3 4 5
1 3 5
pi@raspberrypi:/tmp $
Execution under valgrind to check memory accesses/leaks
pi@raspberrypi:/tmp $ valgrind ./a.out
==2479== Memcheck, a memory error detector
==2479== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2479== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2479== Command: ./a.out
==2479==
1 2 3 4 5
1 3 5
==2479==
==2479== HEAP SUMMARY:
==2479== in use at exit: 0 bytes in 0 blocks
==2479== total heap usage: 6 allocs, 6 frees, 1,064 bytes allocated
==2479==
==2479== All heap blocks were freed -- no leaks are possible
==2479==
==2479== For counts of detected and suppressed errors, rerun with: -v
==2479== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
(edit) In case the length of the list can be even the definition must be changed to :
void deleteAlt(struct Node * head)
{
while ((head != NULL) && (head->next != NULL)) {
Node * d = head->next;
head->next = head->next->next;
free(d);
head = head->next;
}
}
modifying main to check :
int main()
{
{
Node * l = make(1, make(2, make(3, make(4, make(5, NULL)))));
pr(l);
deleteAlt(l);
pr(l);
/* free rest of list */
while (l != NULL) {
Node * n = l->next;
free(l);
l = n;
}
}
{
Node * l = make(1, make(2, make(3, make(4, NULL))));
pr(l);
deleteAlt(l);
pr(l);
/* free rest of list */
while (l != NULL) {
Node * n = l->next;
free(l);
l = n;
}
}
}
Compilation and execution :
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra l.c
pi@raspberrypi:/tmp $ ./a.out
1 2 3 4 5
1 3 5
1 2 3 4
1 3
and under valgrind :
pi@raspberrypi:/tmp $ valgrind ./a.out
==3450== Memcheck, a memory error detector
==3450== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3450== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3450== Command: ./a.out
==3450==
1 2 3 4 5
1 3 5
1 2 3 4
1 3
==3450==
==3450== HEAP SUMMARY:
==3450== in use at exit: 0 bytes in 0 blocks
==3450== total heap usage: 10 allocs, 10 frees, 1,096 bytes allocated
==3450==
==3450== All heap blocks were freed -- no leaks are possible
==3450==
==3450== For counts of detected and suppressed errors, rerun with: -v
==3450== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
C - Segmentation fault when checking if a pointer is NULL
In your add
function, the variable n
is an uninitialized pointer. So it is not the problem of checking it->head
.
Segmentation Fault on Pointer null check
Found the Problem: Change the loop condition to while(!currStack.empty()) {}
C program pointer not holding valid address still not giving segmentation fault
It depends on the value of "cantcatch" - which is undefined (random value).
If the value is out of the memory scope of your program - then the program will segfault.
If it's within the scope of your program then the program will not crash but potentially cause corruption to memory.
These invalid read/writes can easily be caught by memory profiling tools such as "Valgrind".
How to judge whether the incoming buffer is valid in C++?
Don't. Just don't.
Even if you could find a way to check whether the pointer can safely be dereferenced, that doesn't mean it points where you think it does! It might point into your call stack, into your read-only code segment, into the static variables of some library that you're using, or any other place in memory that your program happens to have access to.
The responsibility of passing a valid pointer should be with the caller of the function. To make it harder for the caller to do something stupid, consider passing a std::vector &
or std::vector const &
instead.
Related Topics
Reusing a Port Number in a Udp
Pass in Bash Terminal Variables to a Bash Script
Retrieve Ipv4 and Ipv6 Nameservers Programmatically
Linux: Differencebetween These Two Symbolic Link Commands
Segmentation-Fault Error Happening with Assembly Code Program
Find and Replace a Word with Another in All File Names of a Directory
How to Find Process Using Tcp Port
How to Monitor the Amount of Simd Instruction Usage
Ssh Times Out While Connecting via Ipv6 But Works with Ipv4
Comparing 16 Bit Numbers in Nasm Produces Wrong Results
Python Error "Attributeerror: 'Module' Object Has No Attribute 'Sha1'"
How to Split Flv File by Size Using Ffmpeg or Mencoder or Smth Else
How to Disable Hardware Prefetcher in Core I7
Stack Smashing Code Not Working on Linux Kernel 2.6.38.7... Please Help