Overview
Features
Download
Documentation
Community
Add-Ons & Services

[Linux] Memory Leak - Poco::Path::home()

General discussion regarding the development of POCO for contributors.

[Linux] Memory Leak - Poco::Path::home()

Postby Rabenklaue » 11 Feb 2010, 06:10

Code: Select all
==31728== Memcheck, a memory error detector
==31728== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==31728== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==31728== Command: ./test
==31728==
--31728-- Valgrind options:
--31728--    -v
--31728--    --leak-check=full
--31728--    --show-reachable=yes
--31728--    --suppressions=/home/rabe/.local/projects/valgrind.supressions
--31728-- Contents of /proc/version:
--31728--   Linux version 2.6.31 (root@old) (gcc version 4.4.2 (Gentoo 4.4.2 p1.0) ) #4 SMP Mon Dec 14 00:07:45 CET 2009
--31728-- Arch and hwcaps: X86, x86-sse1-sse2
--31728-- Page sizes: currently 4096, max supported 4096
--31728-- Valgrind library directory: /usr/lib/valgrind
--31728-- Reading syms from /lib/ld-2.11.so (0x4000000)
--31728-- Reading syms from /mnt/crypt.fs/home/indigo/test (0x8048000)
--31728-- Reading syms from /usr/lib/valgrind/memcheck-x86-linux (0x38000000)
--31728--    object doesn't have a symbol table
--31728--    object doesn't have a dynamic symbol table
--31728-- Reading suppressions file: /home/rabe/.local/projects/valgrind.supressions
--31728-- Reading suppressions file: /usr/lib/valgrind/default.supp
--31728-- REDIR: 0x4016d10 (index) redirected to 0x3803b7ef (???)
--31728-- Reading syms from /usr/lib/valgrind/vgpreload_core-x86-linux.so (0x401f000)
--31728--    object doesn't have a symbol table
--31728-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4022000)
--31728--    object doesn't have a symbol table
==31728== WARNING: new redirection conflicts with existing -- ignoring it
--31728--     new: 0x04016d10 (index               ) R-> 0x04026930 index
--31728-- REDIR: 0x4016eb0 (strlen) redirected to 0x4026bd1 (strlen)
--31728-- Reading syms from /usr/lib/libPocoXML.so.9 (0x4048000)
--31728--    object doesn't have a symbol table
--31728-- Reading syms from /usr/lib/gcc/i686-pc-linux-gnu/4.4.2/libstdc++.so.6.0.13 (0x40d0000)
--31728--    object doesn't have a symbol table
--31728-- Reading syms from /lib/libm-2.11.so (0x41bb000)
--31728-- Reading syms from /usr/lib/gcc/i686-pc-linux-gnu/4.4.2/libgcc_s.so.1 (0x41e2000)
--31728--    object doesn't have a symbol table
--31728-- Reading syms from /lib/libc-2.11.so (0x41fe000)
--31728-- Reading syms from /lib/libpthread-2.11.so (0x4343000)
--31728-- Reading syms from /usr/lib/libPocoFoundation.so.9 (0x435c000)
--31728--    object doesn't have a symbol table
--31728-- Reading syms from /lib/libdl-2.11.so (0x44e8000)
--31728-- Reading syms from /lib/librt-2.11.so (0x44ec000)
--31728-- REDIR: 0x4270db0 (index) redirected to 0x40268e6 (index)
--31728-- REDIR: 0x4272b50 (memchr) redirected to 0x4026f56 (memchr)
--31728-- REDIR: 0x4271830 (rindex) redirected to 0x402684a (rindex)
--31728-- REDIR: 0x41831b0 (operator new(unsigned int)) redirected to 0x402618f (operator new(unsigned int))
--31728-- REDIR: 0x4273540 (memcpy) redirected to 0x4026f8e (memcpy)
--31728-- REDIR: 0x4271480 (strlen) redirected to 0x4026bb5 (strlen)
--31728-- REDIR: 0x426dc00 (free) redirected to 0x4025125 (free)
--31728-- REDIR: 0x426dce0 (malloc) redirected to 0x4025729 (malloc)
--31728-- REDIR: 0x4270f90 (strcpy) redirected to 0x4026c09 (strcpy)
--31728-- REDIR: 0x4270f20 (strcmp) redirected to 0x4026e69 (strcmp)
--31728-- REDIR: 0x426d400 (calloc) redirected to 0x40243f0 (calloc)
--31728-- REDIR: 0x41832e2 (operator new[](unsigned int)) redirected to 0x4025c97 (operator new[](unsigned int))
--31728-- REDIR: 0x418100f (operator delete(void*)) redirected to 0x4024cd9 (operator delete(void*))
--31728-- REDIR: 0x4275ea0 (strchrnul) redirected to 0x4027ac6 (strchrnul)
--31728-- REDIR: 0x42730b0 (mempcpy) redirected to 0x4027b05 (mempcpy)
--31728-- REDIR: 0x4273240 (stpcpy) redirected to 0x4027769 (stpcpy)
--31728-- Reading syms from /lib/libnss_compat-2.11.so (0x48f7000)
--31728-- Reading syms from /lib/libnsl-2.11.so (0x48ff000)
--31728-- Reading syms from /lib/libnss_nis-2.11.so (0x4916000)
--31728-- Reading syms from /lib/libnss_files-2.11.so (0x4921000)
--31728-- REDIR: 0x4273050 (memset) redirected to 0x40279fa (memset)
--31728-- REDIR: 0x4272fe0 (memmove) redirected to 0x4027a5f (memmove)
--31728-- REDIR: 0x418105f (operator delete[](void*)) redirected to 0x40247b1 (operator delete[](void*))
--31728-- Discarding syms at 0x48f7e10-0x48fcbf0 in /lib/libnss_compat-2.11.so due to munmap()
--31728-- Discarding syms at 0x4917950-0x491d898 in /lib/libnss_nis-2.11.so due to munmap()
--31728-- Discarding syms at 0x4902170-0x490eddc in /lib/libnsl-2.11.so due to munmap()
--31728-- Discarding syms at 0x4922a00-0x4929cbc in /lib/libnss_files-2.11.so due to munmap()
==31728==
==31728== HEAP SUMMARY:
==31728==     in use at exit: 156 bytes in 11 blocks
==31728==   total heap usage: 351 allocs, 340 frees, 40,958 bytes allocated
==31728==
==31728== Searching for pointers to 11 not-freed blocks
==31728== Checked 129,892 bytes
==31728==
==31728== 8 bytes in 1 blocks are indirectly lost in loss record 1 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBA3B: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8ECB: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44236C8: Poco::Path::Path(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 8 bytes in 1 blocks are indirectly lost in loss record 2 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBA3B: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8EE9: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44236C8: Poco::Path::Path(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 8 bytes in 1 blocks are indirectly lost in loss record 3 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBA3B: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F07: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44236C8: Poco::Path::Path(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 8 bytes in 1 blocks are indirectly lost in loss record 4 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBA3B: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F25: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44236C8: Poco::Path::Path(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 8 bytes in 1 blocks are indirectly lost in loss record 5 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBA3B: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F43: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44236C8: Poco::Path::Path(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 16 bytes in 1 blocks are indirectly lost in loss record 6 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42C9A10: tsearch (in /lib/libc-2.11.so)
==31728==    by 0x42DB9ED: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8ECB: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 16 bytes in 1 blocks are indirectly lost in loss record 7 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42C9A10: tsearch (in /lib/libc-2.11.so)
==31728==    by 0x42DB9ED: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8EE9: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 16 bytes in 1 blocks are indirectly lost in loss record 8 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42C9A10: tsearch (in /lib/libc-2.11.so)
==31728==    by 0x42DB9ED: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F07: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 16 bytes in 1 blocks are indirectly lost in loss record 9 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42C9A10: tsearch (in /lib/libc-2.11.so)
==31728==    by 0x42DB9ED: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F25: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 16 bytes in 1 blocks are indirectly lost in loss record 10 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42C9A10: tsearch (in /lib/libc-2.11.so)
==31728==    by 0x42DB9ED: __nss_lookup_function (in /lib/libc-2.11.so)
==31728==    by 0x48F8F43: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== 156 (36 direct, 120 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 11
==31728==    at 0x40257E6: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==31728==    by 0x42DBE83: nss_parse_service_list (in /lib/libc-2.11.so)
==31728==    by 0x42DC5C8: __nss_database_lookup (in /lib/libc-2.11.so)
==31728==    by 0x48F8EAB: ???
==31728==    by 0x48F9B5C: ???
==31728==    by 0x4294A44: getpwuid_r@@GLIBC_2.1.2 (in /lib/libc-2.11.so)
==31728==    by 0x42943AE: getpwuid (in /lib/libc-2.11.so)
==31728==    by 0x441F324: Poco::PathImpl::homeImpl() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x441F471: Poco::Path::home() (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422BF0: Poco::Path::parseUnix(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x4422E7C: Poco::Path::parseGuess(std::string const&) (in /usr/lib/libPocoFoundation.so.9)
==31728==    by 0x44233AB: Poco::Path::assign(std::string const&, Poco::Path::Style) (in /usr/lib/libPocoFoundation.so.9)
==31728==
==31728== LEAK SUMMARY:
==31728==    definitely lost: 36 bytes in 1 blocks
==31728==    indirectly lost: 120 bytes in 10 blocks
==31728==      possibly lost: 0 bytes in 0 blocks
==31728==    still reachable: 0 bytes in 0 blocks
==31728==         suppressed: 0 bytes in 0 blocks
==31728==
==31728== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 7 from 7)
--31728--
--31728-- used_suppression:      7 ld-2.11.so
==31728==
==31728== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 7 from 7)


Reproducable with following code:
Code: Select all
#include <Poco/SAX/InputSource.h>
#include <Poco/DOM/DOMParser.h>
#include <Poco/DOM/Document.h>
#include <Poco/DOM/AutoPtr.h>

using Poco::XML::InputSource;
using Poco::XML::DOMParser;
using Poco::XML::Document;
using Poco::XML::AutoPtr;

int main() {
   InputSource src("~/test.xml");
   DOMParser parser;
   parser.setFeature(DOMParser::FEATURE_WHITESPACE, true);

   AutoPtr<Document> doc = parser.parse(&src);
}


Whereas "InputSource src("/home/xxx/test.xml");" does not leak. Perhaps someone could track this down.

Stefan
Rabenklaue
 
Posts: 10
Joined: 22 Jan 2010, 07:08
Location: Germany

Re: [Linux] Memory Leak - Poco::Path::home()

Postby dnebing » 04 Feb 2011, 20:19

I'm guessing that the Path_Unix.cpp's implementation of PathImpl::homeImpl() is the culprit.

It uses getpwuid() to find the home directory for the current user (or effective user). According to the man page, getpwuid() returns a pointer to the pwd struct but specifically says not to pass the pointer to free(), and even says that internally getpwuid() may use the pointer over again for subsequent calls...

So your test using "~/test.xml" ends up calling getpwuid() once in order to find the home directory. Since getpwuid() plans on reusing the pointer in the future, it is not released and valgrind sees it as an open allocation. If getpwuid() was going to be reusing the pointer, then this is probably one leak you can ignore (if you call your code in a loop, you should not see a slew of these extra guys hanging around).

That would explain one of them being open, but not the list that valgrind gave you...

I guess the ideal solution would be for POCO to call getpwuid_r() w/ it's own managed buffer; that way there should be no dangling pointers after the call terminates. But as POCO strives to be portable, I can't say that the getpwuid_r() is as portable as getpwuid() is, so it might be using getpwuid() for specific reasons...

But then there's the whole support of threads that POCO has... getpwuid_r() is threadsafe where getpwuid() is not, so I'd question why the implementors chose the non-threadsafe version to begin with...
dnebing
 
Posts: 8
Joined: 03 Feb 2011, 21:42


Return to Contributors

Who is online

Users browsing this forum: No registered users and 0 guests