In Linux, processes can use the /proc/self/mem pseudo-file (and /proc/PID/mem pseudo-files) to read their own memory safely. Memory addresses correspond exactly to file offsets in the pseudo-file. If a memory location cannot be read (because it is not mapped, or is not readable), a read() or pread() will return -1 with errno==EIO.

The list of memory regions is available in the /proc/self/maps pseudo-file (and /proc/PID/maps pseudo-files) as text; not all memory regions that exist are accessible. If a mapping is related to a file, the full path to the file is also listed. For example, on my Linux workstation cat /proc/self/maps outputs
Code:
00400000-0040b000 r-xp 00000000 fc:00 395706             /bin/cat
0060a000-0060b000 r--p 0000a000 fc:00 395706             /bin/cat
0060b000-0060c000 rw-p 0000b000 fc:00 395706             /bin/cat
01419000-0143a000 rw-p 00000000 00:00 0                  [heap]
7fb58c37e000-7fb58c7bd000 r--p 00000000 fc:00 260867     /usr/lib/locale/locale-archive
7fb58c7bd000-7fb58c972000 r-xp 00000000 fc:00 45450      /lib/x86_64-linux-gnu/libc-2.15.so
7fb58c972000-7fb58cb71000 ---p 001b5000 fc:00 45450      /lib/x86_64-linux-gnu/libc-2.15.so
7fb58cb71000-7fb58cb75000 r--p 001b4000 fc:00 45450      /lib/x86_64-linux-gnu/libc-2.15.so
7fb58cb75000-7fb58cb77000 rw-p 001b8000 fc:00 45450      /lib/x86_64-linux-gnu/libc-2.15.so
7fb58cb77000-7fb58cb7c000 rw-p 00000000 00:00 0 
7fb58cb7c000-7fb58cb9e000 r-xp 00000000 fc:00 45470      /lib/x86_64-linux-gnu/ld-2.15.so
7fb58cd75000-7fb58cd78000 rw-p 00000000 00:00 0 
7fb58cd9c000-7fb58cd9e000 rw-p 00000000 00:00 0 
7fb58cd9e000-7fb58cd9f000 r--p 00022000 fc:00 45470      /lib/x86_64-linux-gnu/ld-2.15.so
7fb58cd9f000-7fb58cda1000 rw-p 00023000 fc:00 45470      /lib/x86_64-linux-gnu/ld-2.15.so
7fff9fd7e000-7fff9fd9f000 rw-p 00000000 00:00 0          [stack]
7fff9fdfe000-7fff9fe00000 r-xp 00000000 00:00 0          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]
(16 spaces removed before the last field to make it narrower.)
Note that this pseudo-file is directly provided by the Linux kernel (so no localization etc.), and has a stable format (extremely unlikely to change).

If a process wanted to, it could use raw syscalls (to bypass any interposing libraries) to read the maps pseudo-file to determine which libraries are loaded at which addresses. Using raw syscalls to read the relevant parts of the mem pseudo-file, the process could even examine their code, say compute a checksum or similar, and abort execution if there is anything suspicious.

Because these files are available to the user the process is running as, an inquisitive user can use the above to examine any of their processes. If you have superuser privileges, you can examine all processes this way.

The physical memory of the entire machine is available as an ELF-format pseudo-file, /proc/kcore, but you obviously need superuser privileges to examine it.

I have no idea if Windows provides anything similar.