JackChen255
JackChen255

Reputation: 395

Need to clean up errno before calling function then checking errno?

  1. Do we need to reset errno to zero before calling a function? See below code. Now the scenario is a_dest_path is an existing directory. But when I execute the code, it always tries to mkdir but returns error says that the directory can't be created because it exists. In GDB, I check errno before calling opendir() and errno is 2. And it seems errno is not set to zero during calling opendir(). So do I need to reset errno to zero before calling opendir()?

  2. errno may be changed in system() calls, then in my else if branch I check the result from system() but not opendir(). So after opendir(), do I need to assign errno to a variable then check this variable in the if..elseif..else branch?

DIR *dp = opendir(a_dest_path.c_str());
if (errno == ENOENT) {
    string mkdir_comman = "mkdir " + a_dest_path;
    system(mkdir_command.c_str());
} else if (errno == ENOTDIR) {
    printf("Destination %s exists but is not directory\n", a_dest_path.c_str());
    return k_error_not_directory;
} else if (errno == 0) {
    closedir(dp);
}

Upvotes: 5

Views: 22453

Answers (3)

Alexis Wilke
Alexis Wilke

Reputation: 20818

In your example, as stated by others, there is no need to reset errno.

There are, however, a very few functions which return a number and for them, there is no number that can 100% represent an error occurred. In those few cases, resetting errno is necessary.

One example of such a function is strtol(). On error it returns -1. If you really want to know whether the user passed "-1" or whether an error occurred, then you want to do:

errno = 0;
long r = strtol(input, &end, 10);
if(r == -1 && errno != 0)
    ...handle the error...

In most cases, such functions do spell out the issue in their DESCRIPTION or RETURN VALUE manual sections.

As mentioned by others, a function that returns a pointer is likely to return a nullptr on an error. Then you do not need to reset errno since you should check errno only if the function returned nullptr.

ptr = malloc(123);
if(ptr == nullptr)
   ...handle error, 'errno' gives you extra hints about error...

Upvotes: 4

Deduplicator
Deduplicator

Reputation: 45704

No, there is no need to reset errno before calling the function, because the contract reads:

The opendir() and fdopendir() functions return a pointer to the directory stream. On error, NULL is returned, and errno is set appropriately.

Test the return-value, and only look at errno when you actually have an error!

(realloc is a rare example of a function where under specific circumstances an error cannot be distinguished from success without looking at errno, though it will clear it if that is necessary for disambiguation.)

Upvotes: 8

Remy Lebeau
Remy Lebeau

Reputation: 598134

errno is only meaningful after a real error occurs. You have to check for the error condition first, THEN look at errno, eg:

DIR *dp = opendir(a_dest_path.c_str());
if (dp) {
    closedir(dp);
} else {
    if (errno == ENOENT) {
        string mkdir_comman = "mkdir " + a_dest_path;
        system(mkdir_command.c_str());
    } else if (errno == ENOTDIR) {
        printf("Destination %s exists but is not directory\n", a_dest_path.c_str());
        return k_error_not_directory;
    } else {
        // some other error...
    }
}

Upvotes: 4

Related Questions