Is it safe to call std::memset(pointer, ch, count) with invalid pointer (e.g., nullptr or junk) when count equals 0?
            Asked
            
        
        
            Active
            
        
            Viewed 97 times
        
    3
            
            
         
    
    
        Shawn
        
- 47,241
- 3
- 26
- 60
 
    
    
        user2052436
        
- 4,321
- 1
- 25
- 46
- 
                    It does fall under the as-if rule (https://en.cppreference.com/w/cpp/string/byte/memset). So it seems to be safe to do so. But I can't find explicit confirmation in the standard – Pepijn Kramer Nov 09 '22 at 16:28
- 
                    [C](https://en.cppreference.com/w/c/string/byte/memset) says UB, [C++](https://en.cppreference.com/w/cpp/string/byte/memset) doesn't so I'm not sure – NathanOliver Nov 09 '22 at 16:29
- 
                    I believe the ISO C++ standard refers to the ISO C standard regarding the functions from the C standard library. Therefore, it may be more appropriate to make this a C question than a C++ question, unless a specific C++ rule is relevant here. – Andreas Wenzel Nov 09 '22 at 16:29
- 
                    No, and this has been covered multiple times at Cppcon (don't have the bandwidth right now, but I think https://www.youtube.com/watch?v=yG1OZ69H_-o or https://www.youtube.com/watch?v=g7entxbQOCc will cover it). You're not allowed to pass NULL as either the source or destination, and compilers are free to optimize accordingly. See also: https://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0 – Stephen Newell Nov 09 '22 at 16:56
- 
                    Clang does gives a warning about size 0, MSVC/gcc do not : https://godbolt.org/z/3TzKfGT16. – Pepijn Kramer Nov 09 '22 at 17:07
- 
                    Based on the comments, the TL;DR is: **No**, it is _not_ safe to do this. – Craig Estey Nov 09 '22 at 17:22
- 
                    https://stackoverflow.com/q/8597034/1918193 – Marc Glisse Nov 09 '22 at 18:52
1 Answers
6
            No, that causes undefined behavior. For example:
void* p = get_address(); // may return null
size_t sz = get_size();  // zero if previous returned null
memset(p, 0, sz); // Compiler may assume that p is not null
if (p) { // this null-check can be omitted since we "know" p is not null
  foo(p);
}
And indeed, if you look at the code generated by GCC:
main:
        push    rbx
        call    get_address()
        mov     rbx, rax
        call    get_size()
        mov     rdi, rbx
        xor     esi, esi
        mov     rdx, rax
        call    memset
        mov     rdi, rbx
        call    foo(void*) ; <-- unconditional call
        xor     eax, eax
        pop     rbx
        ret
You can see that the "if" branch is omitted.
 
    
    
        Aykhan Hagverdili
        
- 28,141
- 6
- 41
- 93