Here's the problem: the pointers that malloc() returns are local to the address space of the process that called malloc(). Those values won't mean anything in the context of another process. Hence putting those numbers in shared memory and using them from another process will invoke undefined behaviour. If you're lucky, your program will then crash. If you're not lucky, you might cause a supernova somewhere (a bit of C humour).
So what you need to do is to allocate a separate chunk of shared memory, and write a "malloc" and "free" that use that pool of memory. In other words, you have to write a small memory allocator/deallocator that uses this shared memory pool, and then passes back offsets from. Since all of your objects are the same, this will be pretty trivial.
Notice I said "offsets" and not "addresses". I don't recall anywhere in anything I've ever read that guarantees that the shared memory will be assigned the same address in different processes. Assuming so, and using those values in your lists will likely lead you back to your original problem. So you will have to handle that problem in an intelligent way.
You can write this to be general (will handle any size allocation) or specific (only handles things of your struct Obj type). Either way is fine, but I think the exercise of writing the general will teach you more.
This is a fairly easy task, but there are some things to watch out for. I will give you two:
a) Only ONE process can initialize the shared memory pool. Start that process FIRST, initialize the pool, and THEN start the others. Otherwise, you'll potentially have multiple processes trashing your pool.
b) What happens if a process that is allocating something from this shared pool gets interrupted during the middle of an allocation, and another process also tries to allocate something from this shared pool. Warning: if you do this wrong, Bad Things will happen, and your mother will laugh at you. Note that accessing the list can ALSO lead to the same kinds of problems, because in the general case you don't necessarily know if another cooperating process has manipulated the list.
One other thing: in your post, you had:
*sh = *head;
This is wrong: a) you don't want to change the contents of sh, and b) you want head to point to sh, not the other way around.
HTH