Strange error, argv[4] being set to null when a file exists?

Strange error, argv[4] being set to null when a file exists?

I think reading the code and reading the output would describe this issue the best. When I run the program, when specC doesn't exist, I get the error "Error: opening file out.nes failed." but when I run the program when the file does exist, I get "Error: opening file (null) failed.". I'm having a hard time understanding why this is happening.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<cstdio>

int main(int argc, char* argv[])
	{
	if(argc != 4)
		{
		fprintf(stderr,"\x1b[31;1mError:\x1b[0m 3 arguments needed\n");
		return 1;
		}
	
	FILE* specA;
	FILE* specB;
	FILE* specC;
	
	if((specA = fopen(argv[2],"r")) == NULL)
		{
		fprintf(stderr,"\x1b[31;1mError:\x1b[0m opening file %s failed.\n", argv[2]);
		return 2;
		}
	if((specB = fopen(argv[3],"r")) == NULL)
		{
		fprintf(stderr,"\x1b[31;1mError:\x1b[0m opening file %s failed.\n", argv[3]);
		return 2;
		}
	if((specC = fopen(argv[4],"w+")) == NULL)
		{
		fprintf(stderr,"\x1b[31;1mError:\x1b[0m opening file %s failed.\n", argv[4]);
		return 2;
		}
	
	int C;
	
	for(C = 0;C < 1048576;C++)
		{
		putc(

		(
		getc(specA) +
		getc(specB)
		) /2
		
		, specC);
		}
	}



$ ./exec C/2.nes C/1.nes out.nes //out.nes does not exist.
Error: opening file out.nes failed.
$ ./exec C/2.nes C/1.nes out.nes //out.nes does exist.
Error: opening file (null) failed.
$ ./exec C/2.nes C/1.nes out1.nes //out1.nes does not exist.
Error: opening file out1.nes failed.
$ ./exec C/2.nes C/1.nes out.nes //out.nes does exist.
Error: opening file (null) failed.
$ ./exec C/2.nes C/1.nes out.nes //out.nes does exist.
Error: opening file (null) failed.
$ ./exec C/2.nes C/1.nes out.nes  //out.nes does exist.
Error: opening file (null) failed.


Also, why is this website so broken? It seems to be getting worse every day.
Last edited on
Do you realize that arrays start at zero not one? Are you aware that argv[argc] is guaranteed to be a null pointer?

Edit: And note argv[0] is usually the program name, your command line arguments start at the second element of this array.

Last edited on
I do realize that arrays start at zero. No, I'm pretty sure argv[argc] is NOT guaranteed to be a null pointer, as my faulty program and many faulty programs I've written have demonstrated.

Thanks for explaining my silly mistake, anyways. It's always the simple things...
No, I'm pretty sure argv[argc] is NOT guaranteed to be a null pointer,

Ah, but it is.

From the C99 draft standard.


5.1.2.2.1 Program startup

2. If they are declared, the parameters to the main function shall obey the following
constraints:
— The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.


Look at your error messages "Error: opening file (null) failed."
This demonstrates that the pointer is a NULL pointer. Remember you tried to access argv[4], this would be the same as trying to access argv[argc] in this program (remember argc is equal to 4).



Good point, but in all cases I'm trying to access argv[argc], and some of those cases argv[argc] is equal to "out.nes" and "out1.nes", not always null. If it helps, I'm running gcc main.cpp -o exec to compile, and I'm running gcc 6.3.1-1. I don't know why it isn't null if it says to in the standard, but I know it's not always null via demonstration.
but in all cases I'm trying to access argv[argc]

No, argc is the number of parameters, 4 in this case. You tested argc to insure that it's value was 4, if it wasn't you returned from the function. If it was equal to 4 you proceeded, to the if() statements. In each of those if statements, except the last, you used an array index value that was less than argc those strings would be equal to whatever the corresponding command line argument contained. In your last if statement you tried to use an index value that was equal to argc, which is a NULL pointer as indicated by your error messages.

I don't know why it isn't null if it says to in the standard

argv[argc] was indeed a NULL pointer in your program, remember in this case argv[4] is the same as argv[argc].

For example the following sample run line: "yourProgramName parameter1 parameter2 parameter3" would produce the following output:

argv[0] = "yourProgramName"
argv[1] = "parameter1"
argv[2] = "parameter2"
argv[3] = "parameter3"
argv[4] = NULL

You're not understanding what I'm saying. In the last test case, I was always testing argv[4], but argv[4] was not always null, as demonstrated by:

$ ./exec C/2.nes C/1.nes out.nes (this was typed into a terminal)

Error: opening file out.nes failed. (The output of the program)

The variables, in this case, were equal to:
argv[0] = "./exec"
argv[1] = "C/2.nes"
argv[2] = "C/1.nes"
argv[3] = "out.nes"
argv[4] = (supposed to be null, but actually "out.nes". If it was equal to null, then the output would have been "Error: opening file (null) failed." but it WASN'T in this case.)
You're not understanding what I'm saying. In the last test case, I was always testing argv[4], but argv[4] was not always null, as demonstrated by:


If, as is the case in the OP, "out.nes" doesn't actually exist, then argv[4] would never be evaluated since trying to open "out.nes" (argv[3]) for reading would fail prior to that happening. I would suggest that some of your trials were run in different environments (one where "out.nes" existed and one where it did not.)
Last edited on
Oh! Ugh, I make the silliest mistakes sometimes. I don't get why I keep doing this... I haven't programmed in a while, and I just wrote the program as a fun experiment. How are you guys able to analyze code so well, and able to catch on to things that always seem to go over my head?
Topic archived. No new replies allowed.