--- a/atop.c
+++ b/atop.c
@@ -324,6 +324,8 @@ char      	calcpss    = 0;  /* boolean:
 char      	getwchan   = 0;  /* boolean: obtain wchan string         */
 char      	rmspaces   = 0;  /* boolean: remove spaces from command  */
 		                 /* name in case of parseable output     */
+char		connectgpud    = 0; /* boolean: connect to atopgpud      */
+char		connectnetatop = 0; /* boolean: connect to netatop(bpf)  */
 
 unsigned short	hertz;
 unsigned int	pidwidth;
@@ -619,6 +621,14 @@ main(int argc, char *argv[])
 				rmspaces = 1;
 				break;
 
+                           case 'k':		/* try to open TCP connection to atopgpud */
+				connectgpud = 1;
+				break;
+
+                           case 'K':		/* try to open connection to netatop/netatop-bpf */
+				connectnetatop = 1;
+				break;
+
 			   default:		/* gather other flags */
 				flaglist[i++] = c;
 			}
@@ -736,7 +746,8 @@ main(int argc, char *argv[])
 	/*
  	** open socket to the IP layer to issue getsockopt() calls later on
 	*/
-	netatop_ipopen();
+	if (connectnetatop)
+		netatop_ipopen();
 
 	/*
 	** since privileged activities are finished now, there is no
@@ -839,11 +850,15 @@ engine(void)
 
 	/*
  	** open socket to the atopgpud daemon for GPU statistics
+	** if explicitly required
 	*/
-        nrgpus = gpud_init();
+	if (connectgpud)
+	{
+		nrgpus = gpud_init();
 
-	if (nrgpus)
-		supportflags |= GPUSTAT;
+		if (nrgpus)
+			supportflags |= GPUSTAT;
+	}
 
 	/*
 	** MAIN-LOOP:
@@ -890,7 +905,10 @@ engine(void)
 		** send request for statistics to atopgpud 
 		*/
 		if (nrgpus)
-			gpupending = gpud_statrequest();
+		{
+			if ((gpupending = gpud_statrequest()) == 0)
+				nrgpus = 0;
+		}
 
 		/*
 		** take a snapshot of the current system-level statistics 
@@ -915,28 +933,8 @@ engine(void)
 			// connection lost or timeout on receive?
 			if (nrgpuproc == -1)
 			{
-				int ng;
-
-				// try to reconnect
-        			ng = gpud_init();
-
-				if (ng != nrgpus)	// no success
-					nrgpus = 0;
-
-				if (nrgpus)
-				{
-					// request for stats again
-					if (gpud_statrequest())
-					{
-						// receive stats response
-						nrgpuproc = gpud_statresponse(nrgpus,
-						     cursstat->gpu.gpu, &gp);
-
-						// persistent failure?
-						if (nrgpuproc == -1)
-							nrgpus = 0;
-					}
-				}
+				nrgpus = 0;
+				supportflags &= ~GPUSTAT;
 			}
 
 			cursstat->gpu.nrgpus = nrgpus;
@@ -1025,7 +1023,7 @@ engine(void)
 		/*
  		** merge GPU per-process stats with other per-process stats
 		*/
-		if (nrgpus && nrgpuproc)
+		if (nrgpus && nrgpuproc > 0)
 			gpumergeproc(curtpres, ntaskpres,
 		                     curpexit, nprocexit,
 		 	             gp,       nrgpuproc);
@@ -1056,8 +1054,8 @@ engine(void)
 		if (nprocexitnet > 0)
 			netatop_exiterase();
 
-		if (gp)
-			 free(gp);
+		free(gp);
+		gp = NULL;      // avoid double free
 
 		if (lastcmd == 'r')	/* reset requested ? */
 		{
@@ -1102,6 +1100,8 @@ prusage(char *myname)
 			MRMSPACES);
 	printf("\t  -L  alternate line length (default 80) in case of "
 			"non-screen output\n");
+	printf("\t  -k  try to connect to external atopgpud daemon (default: do not connect)\n");
+	printf("\t  -K  try to connect to netatop/netatop-bpf interface (default: do not connect)\n");
 
 	if (vis.show_usage)
 		(*vis.show_usage)();
--- a/atop.h
+++ b/atop.h
@@ -89,6 +89,7 @@ extern char		calcpss;
 extern char		getwchan;
 extern char		rawname[];
 extern char		rawreadflag;
+extern char		connectnetatop;
 extern char		rmspaces;
 extern time_t		begintime, endtime, cursortime;	// epoch or time in day
 extern char		flaglist[];
--- a/deviate.c
+++ b/deviate.c
@@ -1053,7 +1053,7 @@ deviatsyst(struct sstat *cur, struct sst
 		/*
 		** determine new j
 		*/
-		if (pre->dsk.dsk[j].name)	// existing matching entry
+		if (pre->dsk.dsk[j].name[0])	// existing matching entry
 			j++;
 		else
 			j = realj;		// empty entry: stick to old j
@@ -1122,7 +1122,7 @@ deviatsyst(struct sstat *cur, struct sst
 		/*
 		** determine new j
 		*/
-		if (pre->dsk.mdd[j].name)	// existing matching entry
+		if (pre->dsk.mdd[j].name[0])	// existing matching entry
 			j++;
 		else
 			j = realj;		// empty entry: stick to old j
@@ -1191,7 +1191,7 @@ deviatsyst(struct sstat *cur, struct sst
 		/*
 		** determine new j
 		*/
-		if (pre->dsk.lvm[j].name)	// existing matching entry
+		if (pre->dsk.lvm[j].name[0])	// existing matching entry
 			j++;
 		else
 			j = realj;		// empty entry: stick to old j
--- a/gpucom.c
+++ b/gpucom.c
@@ -43,12 +43,12 @@
 
 #define	GPUDPORT	59123
 
-static void	gputype_parse(char *);
+static int	gputype_parse(char *);
 
-static void	gpustat_parse(int, char *, int,
+static int	gpustat_parse(int, char *, int,
 		                      struct pergpu *, struct gpupidstat *);
-static void	gpuparse(int, char *, struct pergpu *);
-static void	pidparse(int, char *, struct gpupidstat *);
+static int	gpuparse(int, char *, struct pergpu *);
+static int	pidparse(int, char *, struct gpupidstat *);
 static int	rcvuntil(int, char *, int);
 
 static int	actsock = -1;
@@ -150,20 +150,24 @@ gpud_init(void)
 	if ( rcvuntil(actsock, buf, length) == -1)
 	{
 		perror("receive type request from atopgpud");
+		free(buf);
 		goto close_and_return;
 	}
 
 	buf[length] = '\0';
 
-	gputype_parse(buf);
-
-        numgpus = numgpus <= MAXGPU ? numgpus : MAXGPU;
+	if (! gputype_parse(buf))
+	{
+		free(buf);
+		goto close_and_return;
+	}
 
 	return numgpus;
 
     close_and_return:
 	close(actsock);
 	actsock = -1;
+	numgpus = 0;
 	return 0;
 }
 
@@ -176,7 +180,7 @@ gpud_init(void)
 **
 ** Return value:
 ** 	0 in case of failure
-** 	1 in case of success
+** 	1 in case of success (request pending)
 */
 int
 gpud_statrequest(void)
@@ -190,6 +194,7 @@ gpud_statrequest(void)
 	{
 		close(actsock);
 		actsock = -1;
+		numgpus = 0;
 		return 0;
 	}
 
@@ -216,7 +221,7 @@ gpud_statresponse(int maxgpu, struct per
 	uint32_t	prelude;
 	char		*buf = NULL, *p;
 	int		version, length;
-	int		pids = 0;
+	int		maxprocs = 0, nrprocs;
 
 	if (actsock == -1)
 		return -1;
@@ -269,22 +274,22 @@ gpud_statresponse(int maxgpu, struct per
 	*(buf+length) = '\0';
 
 	/*
-	** determine number of per-process stats
-	** and malloc space to parse these stats
+	** determine number of per-process stats in string
+	** and malloc space to store these stats
 	*/
 	for (p=buf; *p; p++)
 	{
 		if (*p == PIDDELIM)
-			pids++;
+			maxprocs++;
 	}
 
 	if (gps)
 	{
-		if (pids)
+		if (maxprocs)
 		{
-			*gps = malloc(pids * sizeof(struct gpupidstat));
-			ptrverify(gps, "Malloc failed for gpu pidstats\n");
-			memset(*gps, 0, pids * sizeof(struct gpupidstat));
+			*gps = malloc(maxprocs * sizeof(struct gpupidstat));
+			ptrverify(*gps, "Malloc failed for gpu pidstats\n");
+			memset(*gps, 0, maxprocs * sizeof(struct gpupidstat));
 		}
 		else
 		{
@@ -295,18 +300,27 @@ gpud_statresponse(int maxgpu, struct per
 	/*
 	** parse stats string for per-gpu stats
 	*/
-	gpustat_parse(version, buf, maxgpu, ggs, gps ? *gps : NULL);
+	if ( (nrprocs =  gpustat_parse(version, buf, maxgpu, ggs, gps ? *gps : NULL)) == -1)
+	{
+		if (gps)
+		{
+			free(*gps);
+			*gps = NULL;    // avoid double free later on
+		}
+
+		goto close_and_return; // inconsistent data received from atopgpud
+	}
 
 	free(buf);
 
-	return pids;
+	return nrprocs;
 
     close_and_return:
-	if (buf)
-		free(buf);
+	free(buf);
 
 	close(actsock);
 	actsock = -1;
+	numgpus = 0;
 	return -1;
 }
 
@@ -314,6 +328,9 @@ gpud_statresponse(int maxgpu, struct per
 /*
 ** Receive given number of bytes from given socket
 ** into given buffer address
+**
+** Return value:  number of bytes received
+**                -1 - failed (including end-of-connection)
 */
 static int
 rcvuntil(int sock, char *buf, int size)
@@ -339,23 +356,27 @@ rcvuntil(int sock, char *buf, int size)
 **
 ** Store the type, busid and tasksupport of every GPU in
 ** static pointer tables
+**
+** Return value:  1 - success
+**                0 - failed
 */
-static void
+static int
 gputype_parse(char *buf)
 {
-	char	*p, *start, **bp, **tp, *cp;
+	char	*p, *start, **bp, **tp, *cp, fails=0;
 
 	/*
 	** determine number of GPUs
 	*/
 	if ( sscanf(buf, "%d@", &numgpus) != 1)
-	{
-		close(actsock);
-		actsock = -1;
-		return;
-	}
+		return 0;
+
+        numgpus = numgpus <= MAXGPU ? numgpus : MAXGPU;
 
-	for (p=buf; *p; p++)	// search for first delimiter
+	/*
+	** search for first GPU delimiter (@)
+	*/
+	for (p=buf; *p; p++)
 	{
 		if (*p == GPUDELIM)
 		{
@@ -364,6 +385,9 @@ gputype_parse(char *buf)
 		}
 	}
 
+	if (*p == 0)	// no delimiter or no data behind delimeter?
+		return 0;
+
 	/*
 	** parse GPU info and build arrays of pointers to the
 	** busid strings, type strings and tasksupport strings.
@@ -380,27 +404,47 @@ gputype_parse(char *buf)
 		ptrverify(gputypes, "Malloc failed for gpu types\n");
 		ptrverify(gputasks, "Malloc failed for gpu tasksup\n");
 
-		for (field=0, start=p; ; p++)
+		for (field=0, start=p; fails == 0; p++)
 		{
 			if (*p == ' ' || *p == '\0' || *p == GPUDELIM)
 			{
 				switch(field)
 				{
 				   case 0:
+					if (bp - gpubusid >= numgpus)
+					{
+						fails++;
+						break; 	// inconsistent with number of GPUs
+					}
+
 					if (p-start <= MAXGPUBUS)
 						*bp++ = start;
 					else
 						*bp++ = p - MAXGPUBUS;
 					break;
 				   case 1:
+					if (tp - gputypes >= numgpus)
+					{
+						fails++;
+						break; 	// inconsistent with number of GPUs
+					}
+
 					if (p-start <= MAXGPUTYPE)
 						*tp++ = start;
 					else
 						*tp++ = p - MAXGPUTYPE;
 					break;
 				   case 2:
+					if (cp - gputasks >= numgpus)
+					{
+						fails++;
+						break; 	// inconsistent with number of GPUs
+					}
+
 					*cp++ = *start;
 					break;
+				   default:
+					fails++;
 				}
 
 				field++;
@@ -418,7 +462,25 @@ gputype_parse(char *buf)
 
 		*bp = NULL;
 		*tp = NULL;
+
+		/*
+		** verify if number of GPUs and supplied per-GPU information
+		** appears to be inconsistent
+		*/
+		if (fails || bp - gpubusid != numgpus || tp - gputypes != numgpus || cp - gputasks != numgpus)
+		{
+			free(gpubusid);
+			free(gputypes);
+			free(gputasks);
+			return 0;
+		}
 	}
+	else
+	{
+		return 0;
+	}
+
+	return 1;
 }
 
 
@@ -429,106 +491,146 @@ gputype_parse(char *buf)
 ** with a '@' delimiter.
 ** Every series with counters on process level is introduced
 ** with a '#' delimiter (last part of the GPU level data).
+**
+** Return value:  valid number of processes 
+**                -1 - failed
 */
-static void
+static int
 gpustat_parse(int version, char *buf, int maxgpu, 
 		struct pergpu *gg, struct gpupidstat *gp)
 {
-	char	*p, *start, delimlast;
-	int	gpunum = 0;
+	char		*p, *pp, *start;
+	int		gpunum, nrprocs = 0;
 
 	/*
 	** parse stats string
 	*/
-	for (p=start=buf, delimlast=DUMMY; gpunum <= maxgpu; p++)
+	for (p=buf; *p && *p != GPUDELIM; p++)	// find first GPU deimiter
+		; 
+
+	if (*p == 0)	// string without GPU delimiter
+		return -1;
+
+	for (p++, start=p, gpunum=0; gpunum < maxgpu; p++)
 	{
-		char delimnow;
+		char delimnext;
 
-		if (*p != '\0' && *p != GPUDELIM && *p != PIDDELIM)
+		// search next GPU delimiter
+		//
+		if (*p && *p != GPUDELIM)
 			continue;
 
 		/*
-		** next delimiter or end-of-string found
+		** next GPU delimiter or end-of-string found
 		*/
-		delimnow = *p;
-		*p       = 0;
-
- 		switch (delimlast)
-		{
-		   case DUMMY:
-			break;
-
-		   case GPUDELIM:
-			gpuparse(version, start, gg);
+		delimnext = *p;
+		*p        = 0;
 
-			strcpy(gg->type,  gputypes[gpunum]);
-			strcpy(gg->busid, gpubusid[gpunum]);
+		/*
+		** parse GPU itself
+		*/
+		if (! gpuparse(version, start, gg))
+			return -1;
 
-			gpunum++;
-			gg++;
-			break;
+		strncpy(gg->type,  gputypes[gpunum], MAXGPUTYPE);
+		strncpy(gg->busid, gpubusid[gpunum], MAXGPUBUS);
 
-		   case PIDDELIM:
-			if (gp)
+		/*
+		** continue searching for per-process stats for this GPU
+		*/
+		if (gp)
+		{
+			for (pp = start; pp < p; pp++)
 			{
-				pidparse(version, start, gp);
+				if (*pp != PIDDELIM)
+					continue;
+
+				// new PID delimiter (#) found
+				//
+				if (! pidparse(version, pp+1, gp))
+					return -1;
 
 				gp->gpu.nrgpus++;
-				gp->gpu.gpulist = 1<<(gpunum-1);
+				gp->gpu.gpulist = 1<<gpunum;
 				gp++;
 
-				(gg-1)->nrprocs++;
+				gg->nrprocs++;	// per GPU
+				nrprocs++;	// total
 			}
 		}
 
-		if (delimnow == 0 || *(p+1) == 0)
+		gpunum++;
+		gg++;
+
+		if (delimnext == 0 || *(p+1) == 0)
 			break;
 
-		start     = p+1;
-		delimlast = delimnow;
+		start = p+1;
 	}
+
+	return nrprocs;
 }
 
 
 /*
 ** Parse GPU statistics string
+**
+** Return value:  1 - success
+**                0 - failed
 */
-static void
+static int
 gpuparse(int version, char *p, struct pergpu *gg)
 {
+	int nr;
+
 	switch (version)
 	{
 	   case 1:
-		(void) sscanf(p, "%d %d %lld %lld %lld %lld %lld %lld", 
+		nr = sscanf(p, "%d %d %lld %lld %lld %lld %lld %lld", 
 			&(gg->gpupercnow), &(gg->mempercnow),
 			&(gg->memtotnow),  &(gg->memusenow),
 			&(gg->samples),    &(gg->gpuperccum),
 			&(gg->memperccum), &(gg->memusecum));
 
+		if (nr < 8)	// parse error: unexpected data
+			return 0;
+
 		gg->nrprocs = 0;
 
 		break;
 	}
+
+	return 1;
 }
 
 
 /*
 ** Parse PID statistics string
+**
+** Return value:  1 - success
+**                0 - failed
 */
-static void
+static int
 pidparse(int version, char *p, struct gpupidstat *gp)
 {
+	int nr;
+
 	switch (version)
 	{
 	   case 1:
-		(void) sscanf(p, "%c %ld %d %d %lld %lld %lld %lld",
+		nr = sscanf(p, "%c %ld %d %d %lld %lld %lld %lld",
 			&(gp->gpu.state),   &(gp->pid),    
 			&(gp->gpu.gpubusy), &(gp->gpu.membusy),
 			&(gp->gpu.timems),
 			&(gp->gpu.memnow), &(gp->gpu.memcum),
 		        &(gp->gpu.sample));
+
+		if (nr < 8)	// parse error: unexpected data
+	 		return 0;
 		break;
 	}
+
+	return 1;
 }
 
 
--- a/photoproc.c
+++ b/photoproc.c
@@ -136,7 +136,8 @@ photoproc(struct tstat *tasklist, int ma
 	*/
 	regainrootprivs();
 
-	netatop_probe();
+	if (connectnetatop)
+		netatop_probe();
 
 	if (supportflags & CGROUPV2)
 		wipecgroupv2();
